mirror of
https://gitea.mayex.net/mayekkuzu/Audinaut.git
synced 2025-01-23 08:14:53 +03:00
IDE-fueled mega refactor
This commit is contained in:
parent
1396ff5e48
commit
c7a49ee88e
6
.gitignore
vendored
6
.gitignore
vendored
@ -37,11 +37,7 @@ captures/
|
|||||||
|
|
||||||
# Intellij
|
# Intellij
|
||||||
*.iml
|
*.iml
|
||||||
.idea/workspace.xml
|
.idea
|
||||||
.idea/tasks.xml
|
|
||||||
.idea/gradle.xml
|
|
||||||
.idea/dictionaries
|
|
||||||
.idea/libraries
|
|
||||||
|
|
||||||
# External native build folder generated in Android Studio 2.2 and later
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
|
||||||
</project>
|
|
9
.idea/modules.xml
generated
9
.idea/modules.xml
generated
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/Audinaut.iml" filepath="$PROJECT_DIR$/Audinaut.iml" />
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
12
.idea/runConfigurations.xml
generated
12
.idea/runConfigurations.xml
generated
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RunConfigurationProducerService">
|
|
||||||
<option name="ignoredProducers">
|
|
||||||
<set>
|
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,100 +1,120 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="net.nullsum.audinaut"
|
package="net.nullsum.audinaut"
|
||||||
android:installLocation="internalOnly">
|
android:installLocation="internalOnly">
|
||||||
|
|
||||||
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
android:targetPackage="net.nullsum.audinaut"
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
android:label="Tests" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_PHONE_STATE"
|
||||||
|
android:maxSdkVersion="22" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
android:name="android.hardware.touchscreen"
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
android:required="false" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
android:name="android.hardware.bluetooth"
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
android:required="false" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.READ_LOGS"/>
|
android:name="android.hardware.microphone"
|
||||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
android:required="false" />
|
||||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
android:name="android.hardware.wifi"
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
android:required="false" />
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="22"/>
|
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
<supports-screens
|
||||||
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
|
android:anyDensity="true"
|
||||||
<uses-feature android:name="android.hardware.microphone" android:required="false" />
|
android:largeScreens="true"
|
||||||
<uses-feature android:name="android.hardware.wifi" android:required="false" />
|
android:normalScreens="true"
|
||||||
|
android:smallScreens="true"
|
||||||
|
android:xlargeScreens="true" />
|
||||||
|
|
||||||
<supports-screens android:anyDensity="true" android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
|
<application
|
||||||
|
|
||||||
<application android:label="@string/common.appname"
|
|
||||||
android:backupAgent="net.nullsum.audinaut.util.SettingsBackupAgent"
|
android:backupAgent="net.nullsum.audinaut.util.SettingsBackupAgent"
|
||||||
android:icon="@drawable/launch"
|
android:icon="@drawable/launch"
|
||||||
|
android:label="@string/common.appname"
|
||||||
android:theme="@style/LaunchScreen">
|
android:theme="@style/LaunchScreen">
|
||||||
|
|
||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
|
|
||||||
<activity android:name="net.nullsum.audinaut.activity.SubsonicFragmentActivity"
|
<activity
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:name="net.nullsum.audinaut.activity.SubsonicFragmentActivity"
|
||||||
android:launchMode="singleTask">
|
android:configChanges="orientation|keyboardHidden"
|
||||||
|
android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="net.nullsum.audinaut.activity.SettingsActivity"
|
<activity
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:name="net.nullsum.audinaut.activity.SettingsActivity"
|
||||||
android:launchMode="singleTask"/>
|
android:configChanges="orientation|keyboardHidden"
|
||||||
|
android:launchMode="singleTask" />
|
||||||
|
|
||||||
<activity android:name="net.nullsum.audinaut.activity.VoiceQueryReceiverActivity"
|
<activity
|
||||||
android:launchMode="singleTask">
|
android:name="net.nullsum.audinaut.activity.VoiceQueryReceiverActivity"
|
||||||
|
android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="net.nullsum.audinaut.activity.QueryReceiverActivity"
|
<activity
|
||||||
android:launchMode="singleTask">
|
android:name="net.nullsum.audinaut.activity.QueryReceiverActivity"
|
||||||
|
android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEARCH"/>
|
<action android:name="android.intent.action.SEARCH" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
|
<meta-data
|
||||||
|
android:name="android.app.searchable"
|
||||||
|
android:resource="@xml/searchable" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="net.nullsum.audinaut.activity.EditPlayActionActivity"
|
android:name="net.nullsum.audinaut.activity.EditPlayActionActivity"
|
||||||
android:label="@string/tasker.start_playing"
|
android:icon="@drawable/launch"
|
||||||
android:icon="@drawable/launch">
|
android:label="@string/tasker.start_playing">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
|
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service android:name=".service.DownloadService"
|
<service
|
||||||
android:label="Audinaut Playback Service"/>
|
android:name=".service.DownloadService"
|
||||||
|
android:label="Audinaut Playback Service" />
|
||||||
|
|
||||||
<service android:name="net.nullsum.audinaut.service.sync.AuthenticatorService">
|
<service android:name="net.nullsum.audinaut.service.sync.AuthenticatorService">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
<action android:name="android.accounts.AccountAuthenticator" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data android:name="android.accounts.AccountAuthenticator"
|
<meta-data
|
||||||
|
android:name="android.accounts.AccountAuthenticator"
|
||||||
android:resource="@xml/authenticator" />
|
android:resource="@xml/authenticator" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service android:name="net.nullsum.audinaut.service.HeadphoneListenerService"
|
<service
|
||||||
android:label="Audinaut Headphone Listener"/>
|
android:name="net.nullsum.audinaut.service.HeadphoneListenerService"
|
||||||
<receiver
|
android:label="Audinaut Headphone Listener" />
|
||||||
android:name="net.nullsum.audinaut.receiver.BootReceiver">
|
|
||||||
|
<receiver android:name="net.nullsum.audinaut.receiver.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
@ -106,7 +126,7 @@
|
|||||||
|
|
||||||
<receiver android:name="net.nullsum.audinaut.receiver.A2dpIntentReceiver">
|
<receiver android:name="net.nullsum.audinaut.receiver.A2dpIntentReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.music.playstatusrequest"/>
|
<action android:name="android.music.playstatusrequest" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
@ -114,48 +134,59 @@
|
|||||||
android:name="net.nullsum.audinaut.provider.AudinautWidget4x1"
|
android:name="net.nullsum.audinaut.provider.AudinautWidget4x1"
|
||||||
android:label="@string/widget.4x1">
|
android:label="@string/widget.4x1">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget4x1"/>
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/appwidget4x1" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name="net.nullsum.audinaut.provider.AudinautWidget4x2"
|
android:name="net.nullsum.audinaut.provider.AudinautWidget4x2"
|
||||||
android:label="@string/widget.4x2">
|
android:label="@string/widget.4x2">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget4x2"/>
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/appwidget4x2" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name="net.nullsum.audinaut.provider.AudinautWidget4x3"
|
android:name="net.nullsum.audinaut.provider.AudinautWidget4x3"
|
||||||
android:label="@string/widget.4x3">
|
android:label="@string/widget.4x3">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget4x3"/>
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/appwidget4x3" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name="net.nullsum.audinaut.provider.AudinautWidget4x4"
|
android:name="net.nullsum.audinaut.provider.AudinautWidget4x4"
|
||||||
android:label="@string/widget.4x4">
|
android:label="@string/widget.4x4">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget4x4"/>
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/appwidget4x4" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="net.nullsum.audinaut.receiver.PlayActionReceiver">
|
android:name="net.nullsum.audinaut.receiver.PlayActionReceiver"
|
||||||
|
android:permission="">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
|
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<provider android:name="net.nullsum.audinaut.provider.AudinautSearchProvider"
|
<provider
|
||||||
android:authorities="net.nullsum.audinaut.provider.AudinautSearchProvider"/>
|
android:name="net.nullsum.audinaut.provider.AudinautSearchProvider"
|
||||||
|
android:authorities="net.nullsum.audinaut.provider.AudinautSearchProvider" />
|
||||||
|
|
||||||
<meta-data android:name="android.app.default_searchable"
|
<meta-data
|
||||||
android:value="net.nullsum.audinaut.activity.QueryReceiverActivity"/>
|
android:name="android.app.default_searchable"
|
||||||
|
android:value="net.nullsum.audinaut.activity.QueryReceiverActivity" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -16,12 +16,10 @@
|
|||||||
package net.nullsum.audinaut.activity;
|
package net.nullsum.audinaut.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -29,13 +27,9 @@ import android.view.View;
|
|||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
@ -45,6 +39,9 @@ import net.nullsum.audinaut.util.Constants;
|
|||||||
import net.nullsum.audinaut.util.LoadingTask;
|
import net.nullsum.audinaut.util.LoadingTask;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class EditPlayActionActivity extends SubsonicActivity {
|
public class EditPlayActionActivity extends SubsonicActivity {
|
||||||
private CheckBox shuffleCheckbox;
|
private CheckBox shuffleCheckbox;
|
||||||
private CheckBox startYearCheckbox;
|
private CheckBox startYearCheckbox;
|
||||||
@ -64,36 +61,23 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
final Activity context = this;
|
final Activity context = this;
|
||||||
doNothing = context.getResources().getString(R.string.tasker_edit_do_nothing);
|
doNothing = context.getResources().getString(R.string.tasker_edit_do_nothing);
|
||||||
|
|
||||||
shuffleCheckbox = (CheckBox) findViewById(R.id.edit_shuffle_checkbox);
|
shuffleCheckbox = findViewById(R.id.edit_shuffle_checkbox);
|
||||||
shuffleCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
shuffleCheckbox.setOnCheckedChangeListener((view, isChecked) -> {
|
||||||
@Override
|
startYearCheckbox.setEnabled(isChecked);
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
endYearCheckbox.setEnabled(isChecked);
|
||||||
startYearCheckbox.setEnabled(isChecked);
|
genreButton.setEnabled(isChecked);
|
||||||
endYearCheckbox.setEnabled(isChecked);
|
|
||||||
genreButton.setEnabled(isChecked);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
startYearCheckbox = (CheckBox) findViewById(R.id.edit_start_year_checkbox);
|
startYearCheckbox = findViewById(R.id.edit_start_year_checkbox);
|
||||||
startYearBox = (EditText) findViewById(R.id.edit_start_year);
|
startYearBox = findViewById(R.id.edit_start_year);
|
||||||
// Disable/enable number box if checked
|
// Disable/enable number box if checked
|
||||||
startYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
startYearCheckbox.setOnCheckedChangeListener((view, isChecked) -> startYearBox.setEnabled(isChecked));
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
|
||||||
startYearBox.setEnabled(isChecked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
endYearCheckbox = (CheckBox) findViewById(R.id.edit_end_year_checkbox);
|
endYearCheckbox = findViewById(R.id.edit_end_year_checkbox);
|
||||||
endYearBox = (EditText) findViewById(R.id.edit_end_year);
|
endYearBox = findViewById(R.id.edit_end_year);
|
||||||
endYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
endYearCheckbox.setOnCheckedChangeListener((view, isChecked) -> endYearBox.setEnabled(isChecked));
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
|
||||||
endYearBox.setEnabled(isChecked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
genreButton = (Button) findViewById(R.id.edit_genre_spinner);
|
genreButton = findViewById(R.id.edit_genre_spinner);
|
||||||
genreButton.setOnClickListener(new View.OnClickListener() {
|
genreButton.setOnClickListener(new View.OnClickListener() {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
new LoadingTask<List<Genre>>(context, true) {
|
new LoadingTask<List<Genre>>(context, true) {
|
||||||
@ -105,24 +89,22 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(final List<Genre> genres) {
|
protected void done(final List<Genre> genres) {
|
||||||
List<String> names = new ArrayList<String>();
|
List<String> names = new ArrayList<>();
|
||||||
String blank = context.getResources().getString(R.string.select_genre_blank);
|
String blank = context.getResources().getString(R.string.select_genre_blank);
|
||||||
names.add(doNothing);
|
names.add(doNothing);
|
||||||
names.add(blank);
|
names.add(blank);
|
||||||
for(Genre genre: genres) {
|
for (Genre genre : genres) {
|
||||||
names.add(genre.getName());
|
names.add(genre.getName());
|
||||||
}
|
}
|
||||||
final List<String> finalNames = names;
|
final List<String> finalNames = names;
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
builder.setTitle(R.string.shuffle_pick_genre)
|
builder.setTitle(R.string.shuffle_pick_genre)
|
||||||
.setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
|
.setItems(names.toArray(new CharSequence[names.size()]), (dialog, which) -> {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
if (which == 1) {
|
||||||
if(which == 1) {
|
genreButton.setText("");
|
||||||
genreButton.setText("");
|
} else {
|
||||||
} else {
|
genreButton.setText(finalNames.get(which));
|
||||||
genreButton.setText(finalNames.get(which));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
@ -145,36 +127,36 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
});
|
});
|
||||||
genreButton.setText(doNothing);
|
genreButton.setText(doNothing);
|
||||||
|
|
||||||
offlineSpinner = (Spinner) findViewById(R.id.edit_offline_spinner);
|
offlineSpinner = findViewById(R.id.edit_offline_spinner);
|
||||||
ArrayAdapter<CharSequence> offlineAdapter = ArrayAdapter.createFromResource(this, R.array.editServerOptions, android.R.layout.simple_spinner_item);
|
ArrayAdapter<CharSequence> offlineAdapter = ArrayAdapter.createFromResource(this, R.array.editServerOptions, android.R.layout.simple_spinner_item);
|
||||||
offlineAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
offlineAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
offlineSpinner.setAdapter(offlineAdapter);
|
offlineSpinner.setAdapter(offlineAdapter);
|
||||||
|
|
||||||
// Setup default for everything
|
// Setup default for everything
|
||||||
Bundle extras = getIntent().getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
Bundle extras = getIntent().getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||||
if(extras != null) {
|
if (extras != null) {
|
||||||
if(extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) {
|
if (extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) {
|
||||||
shuffleCheckbox.setChecked(true);
|
shuffleCheckbox.setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
String startYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, null);
|
String startYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, null);
|
||||||
if(startYear != null) {
|
if (startYear != null) {
|
||||||
startYearCheckbox.setEnabled(true);
|
startYearCheckbox.setEnabled(true);
|
||||||
startYearBox.setText(startYear);
|
startYearBox.setText(startYear);
|
||||||
}
|
}
|
||||||
String endYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, null);
|
String endYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, null);
|
||||||
if(endYear != null) {
|
if (endYear != null) {
|
||||||
endYearCheckbox.setEnabled(true);
|
endYearCheckbox.setEnabled(true);
|
||||||
endYearBox.setText(endYear);
|
endYearBox.setText(endYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
String genre = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, doNothing);
|
String genre = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, doNothing);
|
||||||
if(genre != null) {
|
if (genre != null) {
|
||||||
genreButton.setText(genre);
|
genreButton.setText(genre);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offline = extras.getInt(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
int offline = extras.getInt(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
||||||
if(offline != 0) {
|
if (offline != 0) {
|
||||||
offlineSpinner.setSelection(offline);
|
offlineSpinner.setSelection(offline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,13 +173,13 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(item.getItemId() == android.R.id.home) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
cancel();
|
cancel();
|
||||||
return true;
|
return true;
|
||||||
} else if(item.getItemId() == R.id.menu_accept) {
|
} else if (item.getItemId() == R.id.menu_accept) {
|
||||||
accept();
|
accept();
|
||||||
return true;
|
return true;
|
||||||
} else if(item.getItemId() == R.id.menu_cancel) {
|
} else if (item.getItemId() == R.id.menu_cancel) {
|
||||||
cancel();
|
cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -215,21 +197,21 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
boolean shuffle = shuffleCheckbox.isChecked();
|
boolean shuffle = shuffleCheckbox.isChecked();
|
||||||
data.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, shuffle);
|
data.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, shuffle);
|
||||||
if(shuffle) {
|
if (shuffle) {
|
||||||
if(startYearCheckbox.isChecked()) {
|
if (startYearCheckbox.isChecked()) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYearBox.getText().toString());
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYearBox.getText().toString());
|
||||||
}
|
}
|
||||||
if(endYearCheckbox.isChecked()) {
|
if (endYearCheckbox.isChecked()) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYearBox.getText().toString());
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYearBox.getText().toString());
|
||||||
}
|
}
|
||||||
String genre = genreButton.getText().toString();
|
String genre = genreButton.getText().toString();
|
||||||
if(!genre.equals(doNothing)) {
|
if (!genre.equals(doNothing)) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int offline = offlineSpinner.getSelectedItemPosition();
|
int offline = offlineSpinner.getSelectedItemPosition();
|
||||||
if(offline != 0) {
|
if (offline != 0) {
|
||||||
data.putInt(Constants.PREFERENCES_KEY_OFFLINE, offline);
|
data.putInt(Constants.PREFERENCES_KEY_OFFLINE, offline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +220,7 @@ public class EditPlayActionActivity extends SubsonicActivity {
|
|||||||
setResult(Activity.RESULT_OK, intent);
|
setResult(Activity.RESULT_OK, intent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancel() {
|
private void cancel() {
|
||||||
setResult(Activity.RESULT_CANCELED);
|
setResult(Activity.RESULT_CANCELED);
|
||||||
finish();
|
finish();
|
||||||
|
@ -23,13 +23,9 @@ import android.app.Activity;
|
|||||||
import android.app.SearchManager;
|
import android.app.SearchManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.SearchRecentSuggestions;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.provider.AudinautSearchProvider;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives search queries and forwards to the SearchFragment.
|
* Receives search queries and forwards to the SearchFragment.
|
||||||
@ -38,8 +34,6 @@ import net.nullsum.audinaut.provider.AudinautSearchProvider;
|
|||||||
*/
|
*/
|
||||||
public class QueryReceiverActivity extends Activity {
|
public class QueryReceiverActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = QueryReceiverActivity.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -47,11 +41,10 @@ public class QueryReceiverActivity extends Activity {
|
|||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||||
doSearch();
|
doSearch();
|
||||||
} else if(Intent.ACTION_VIEW.equals(intent.getAction())) {
|
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||||
showResult(intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
|
showResult(intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
Util.disablePendingTransition(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSearch() {
|
private void doSearch() {
|
||||||
@ -63,15 +56,16 @@ public class QueryReceiverActivity extends Activity {
|
|||||||
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showResult(String albumId, String name) {
|
private void showResult(String albumId, String name) {
|
||||||
if (albumId != null) {
|
if (albumId != null) {
|
||||||
Intent intent = new Intent(this, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(this, SubsonicFragmentActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
||||||
if(albumId.indexOf("ar-") == 0) {
|
if (albumId.indexOf("ar-") == 0) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
albumId = albumId.replace("ar-", "");
|
albumId = albumId.replace("ar-", "");
|
||||||
} else if(albumId.indexOf("so-") == 0) {
|
} else if (albumId.indexOf("so-") == 0) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
|
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
|
||||||
albumId = albumId.replace("so-", "");
|
albumId = albumId.replace("so-", "");
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.activity;
|
package net.nullsum.audinaut.activity;
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
|
||||||
@ -28,8 +27,6 @@ import net.nullsum.audinaut.fragments.SettingsFragment;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public class SettingsActivity extends SubsonicActivity {
|
public class SettingsActivity extends SubsonicActivity {
|
||||||
private static final String TAG = SettingsActivity.class.getSimpleName();
|
|
||||||
private PreferenceCompatFragment fragment;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -38,7 +35,7 @@ public class SettingsActivity extends SubsonicActivity {
|
|||||||
setContentView(R.layout.settings_activity);
|
setContentView(R.layout.settings_activity);
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
fragment = new SettingsFragment();
|
PreferenceCompatFragment fragment = new SettingsFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, R.xml.settings);
|
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, R.xml.settings);
|
||||||
|
|
||||||
@ -50,7 +47,7 @@ public class SettingsActivity extends SubsonicActivity {
|
|||||||
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
Toolbar mainToolbar = findViewById(R.id.main_toolbar);
|
||||||
setSupportActionBar(mainToolbar);
|
setSupportActionBar(mainToolbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,116 +18,108 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.activity;
|
package net.nullsum.audinaut.activity;
|
||||||
|
|
||||||
import android.app.UiModeManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.design.widget.NavigationView;
|
import android.support.design.widget.NavigationView;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.app.AppCompatDelegate;
|
import android.support.v7.app.AppCompatDelegate;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import net.nullsum.audinaut.R;
|
||||||
|
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
||||||
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
|
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
||||||
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
import net.nullsum.audinaut.util.DrawableTint;
|
||||||
|
import net.nullsum.audinaut.util.ImageLoader;
|
||||||
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
|
import net.nullsum.audinaut.util.ThemeUtil;
|
||||||
|
import net.nullsum.audinaut.util.UserUtil;
|
||||||
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import static android.Manifest.permission;
|
||||||
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
|
||||||
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
|
||||||
import net.nullsum.audinaut.util.DrawableTint;
|
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.ThemeUtil;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
|
||||||
import net.nullsum.audinaut.util.UserUtil;
|
|
||||||
|
|
||||||
import static android.Manifest.*;
|
|
||||||
|
|
||||||
public class SubsonicActivity extends AppCompatActivity implements OnItemSelectedListener {
|
public class SubsonicActivity extends AppCompatActivity implements OnItemSelectedListener {
|
||||||
private static final String TAG = SubsonicActivity.class.getSimpleName();
|
private static final String TAG = SubsonicActivity.class.getSimpleName();
|
||||||
private static ImageLoader IMAGE_LOADER;
|
|
||||||
protected static String theme;
|
|
||||||
protected static boolean fullScreen;
|
|
||||||
protected static boolean actionbarColored;
|
|
||||||
private static final int MENU_GROUP_SERVER = 10;
|
private static final int MENU_GROUP_SERVER = 10;
|
||||||
private static final int MENU_ITEM_SERVER_BASE = 100;
|
private static final int MENU_ITEM_SERVER_BASE = 100;
|
||||||
private static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
private static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
||||||
|
private static String theme;
|
||||||
private final List<Runnable> afterServiceAvailable = new ArrayList<>();
|
private static boolean fullScreen;
|
||||||
private boolean drawerIdle = true;
|
private static boolean actionbarColored;
|
||||||
private boolean destroyed = false;
|
private static ImageLoader IMAGE_LOADER;
|
||||||
private boolean finished = false;
|
|
||||||
protected List<SubsonicFragment> backStack = new ArrayList<SubsonicFragment>();
|
|
||||||
protected SubsonicFragment currentFragment;
|
|
||||||
protected View primaryContainer;
|
|
||||||
protected View secondaryContainer;
|
|
||||||
protected boolean touchscreen = true;
|
|
||||||
protected Handler handler = new Handler();
|
|
||||||
Spinner actionBarSpinner;
|
|
||||||
ArrayAdapter<CharSequence> spinnerAdapter;
|
|
||||||
ViewGroup rootView;
|
|
||||||
DrawerLayout drawer;
|
|
||||||
ActionBarDrawerToggle drawerToggle;
|
|
||||||
NavigationView drawerList;
|
|
||||||
View drawerHeader;
|
|
||||||
ImageView drawerHeaderToggle;
|
|
||||||
TextView drawerServerName;
|
|
||||||
TextView drawerUserName;
|
|
||||||
int lastSelectedPosition = 0;
|
|
||||||
boolean showingTabs = true;
|
|
||||||
boolean drawerOpen = false;
|
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<SubsonicFragment> backStack = new ArrayList<>();
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
private final List<Runnable> afterServiceAvailable = new ArrayList<>();
|
||||||
|
SubsonicFragment currentFragment;
|
||||||
|
View secondaryContainer;
|
||||||
|
DrawerLayout drawer;
|
||||||
|
ActionBarDrawerToggle drawerToggle;
|
||||||
|
NavigationView drawerList;
|
||||||
|
int lastSelectedPosition = 0;
|
||||||
|
private boolean touchscreen = true;
|
||||||
|
private Spinner actionBarSpinner;
|
||||||
|
private ArrayAdapter<CharSequence> spinnerAdapter;
|
||||||
|
private View drawerHeader;
|
||||||
|
private ImageView drawerHeaderToggle;
|
||||||
|
private TextView drawerServerName;
|
||||||
|
private TextView drawerUserName;
|
||||||
|
private boolean showingTabs = true;
|
||||||
|
private boolean drawerOpen = false;
|
||||||
|
private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
|
||||||
|
private boolean drawerIdle = true;
|
||||||
|
private boolean destroyed = false;
|
||||||
|
|
||||||
|
public synchronized static ImageLoader getStaticImageLoader(Context context) {
|
||||||
|
if (IMAGE_LOADER == null) {
|
||||||
|
IMAGE_LOADER = new ImageLoader(context);
|
||||||
|
}
|
||||||
|
return IMAGE_LOADER;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(Bundle bundle) {
|
||||||
UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
|
|
||||||
PackageManager pm = getPackageManager();
|
PackageManager pm = getPackageManager();
|
||||||
if(!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
|
if (!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
|
||||||
touchscreen = false;
|
touchscreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,16 +130,16 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
startService(new Intent(this, DownloadService.class));
|
startService(new Intent(this, DownloadService.class));
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
if(getIntent().hasExtra(Constants.FRAGMENT_POSITION)) {
|
if (getIntent().hasExtra(Constants.FRAGMENT_POSITION)) {
|
||||||
lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0);
|
lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preferencesListener == null) {
|
if (preferencesListener == null) {
|
||||||
Util.getPreferences(this).registerOnSharedPreferenceChangeListener(preferencesListener);
|
Util.getPreferences(this).registerOnSharedPreferenceChangeListener(preferencesListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
ActivityCompat.requestPermissions(this, new String[]{ permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
|
ActivityCompat.requestPermissions(this, new String[]{permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,9 +148,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
|
case PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
|
||||||
// If request is cancelled, the result arrays are empty.
|
// If request is cancelled, the result arrays are empty.
|
||||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (!(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
|
||||||
|
|
||||||
} else {
|
|
||||||
Util.toast(this, R.string.permission_external_storage_failed);
|
Util.toast(this, R.string.permission_external_storage_failed);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@ -170,23 +160,23 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
super.onPostCreate(savedInstanceState);
|
super.onPostCreate(savedInstanceState);
|
||||||
|
|
||||||
if(spinnerAdapter == null) {
|
if (spinnerAdapter == null) {
|
||||||
createCustomActionBarView();
|
createCustomActionBarView();
|
||||||
}
|
}
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
|
||||||
if(Util.shouldStartOnHeadphones(this)) {
|
if (Util.shouldStartOnHeadphones(this)) {
|
||||||
Intent serviceIntent = new Intent();
|
Intent serviceIntent = new Intent();
|
||||||
serviceIntent.setClassName(this.getPackageName(), HeadphoneListenerService.class.getName());
|
serviceIntent.setClassName(this.getPackageName(), HeadphoneListenerService.class.getName());
|
||||||
this.startService(serviceIntent);
|
this.startService(serviceIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createCustomActionBarView() {
|
private void createCustomActionBarView() {
|
||||||
actionBarSpinner = (Spinner) getLayoutInflater().inflate(R.layout.actionbar_spinner, null);
|
actionBarSpinner = (Spinner) getLayoutInflater().inflate(R.layout.actionbar_spinner, null);
|
||||||
if((this instanceof SubsonicFragmentActivity || this instanceof SettingsActivity) && (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true) || ThemeUtil.getThemeRes(this) != R.style.Theme_Audinaut_Light_No_Color)) {
|
if ((this instanceof SubsonicFragmentActivity || this instanceof SettingsActivity) && (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true) || ThemeUtil.getThemeRes(this) != R.style.Theme_Audinaut_Light_No_Color)) {
|
||||||
actionBarSpinner.setBackgroundDrawable(DrawableTint.getTintedDrawableFromColor(this, R.drawable.abc_spinner_mtrl_am_alpha, android.R.color.white));
|
actionBarSpinner.setBackground(DrawableTint.getTintedDrawableFromColor(this));
|
||||||
}
|
}
|
||||||
spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item);
|
spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item);
|
||||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
@ -228,91 +218,79 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
Util.getPreferences(this).unregisterOnSharedPreferenceChangeListener(preferencesListener);
|
Util.getPreferences(this).unregisterOnSharedPreferenceChangeListener(preferencesListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
super.finish();
|
|
||||||
Util.disablePendingTransition(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setContentView(int viewId) {
|
public void setContentView(int viewId) {
|
||||||
super.setContentView(R.layout.abstract_activity);
|
super.setContentView(R.layout.abstract_activity);
|
||||||
rootView = (ViewGroup) findViewById(R.id.content_frame);
|
ViewGroup rootView = findViewById(R.id.content_frame);
|
||||||
|
|
||||||
if(viewId != 0) {
|
if (viewId != 0) {
|
||||||
LayoutInflater layoutInflater = getLayoutInflater();
|
LayoutInflater layoutInflater = getLayoutInflater();
|
||||||
layoutInflater.inflate(viewId, rootView);
|
layoutInflater.inflate(viewId, rootView);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawerList = (NavigationView) findViewById(R.id.left_drawer);
|
drawerList = findViewById(R.id.left_drawer);
|
||||||
drawerList.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
|
drawerList.setNavigationItemSelectedListener(menuItem -> {
|
||||||
@Override
|
if (showingTabs) {
|
||||||
public boolean onNavigationItemSelected(final MenuItem menuItem) {
|
// Settings are on a different selectable track
|
||||||
if(showingTabs) {
|
if (menuItem.getItemId() != R.id.drawer_settings && menuItem.getItemId() != R.id.drawer_offline) {
|
||||||
// Settings are on a different selectable track
|
menuItem.setChecked(true);
|
||||||
if (menuItem.getItemId() != R.id.drawer_settings && menuItem.getItemId() != R.id.drawer_offline) {
|
lastSelectedPosition = menuItem.getItemId();
|
||||||
menuItem.setChecked(true);
|
|
||||||
lastSelectedPosition = menuItem.getItemId();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
|
||||||
case R.id.drawer_library:
|
|
||||||
drawerItemSelected("Artist");
|
|
||||||
return true;
|
|
||||||
case R.id.drawer_playlists:
|
|
||||||
drawerItemSelected("Playlist");
|
|
||||||
return true;
|
|
||||||
case R.id.drawer_downloading:
|
|
||||||
drawerItemSelected("Download");
|
|
||||||
return true;
|
|
||||||
case R.id.drawer_offline:
|
|
||||||
toggleOffline();
|
|
||||||
return true;
|
|
||||||
case R.id.drawer_settings:
|
|
||||||
startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class));
|
|
||||||
drawer.closeDrawers();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE;
|
|
||||||
SubsonicActivity.this.setActiveServer(activeServer);
|
|
||||||
populateTabs();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
switch (menuItem.getItemId()) {
|
||||||
|
case R.id.drawer_library:
|
||||||
|
drawerItemSelected("Artist");
|
||||||
|
return true;
|
||||||
|
case R.id.drawer_playlists:
|
||||||
|
drawerItemSelected("Playlist");
|
||||||
|
return true;
|
||||||
|
case R.id.drawer_downloading:
|
||||||
|
drawerItemSelected("Download");
|
||||||
|
return true;
|
||||||
|
case R.id.drawer_offline:
|
||||||
|
toggleOffline();
|
||||||
|
return true;
|
||||||
|
case R.id.drawer_settings:
|
||||||
|
startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class));
|
||||||
|
drawer.closeDrawers();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE;
|
||||||
|
SubsonicActivity.this.setActiveServer(activeServer);
|
||||||
|
populateTabs();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
drawerHeader = drawerList.inflateHeaderView(R.layout.drawer_header);
|
drawerHeader = drawerList.inflateHeaderView(R.layout.drawer_header);
|
||||||
drawerHeader.setOnClickListener(new View.OnClickListener() {
|
drawerHeader.setOnClickListener(v -> {
|
||||||
@Override
|
if (showingTabs) {
|
||||||
public void onClick(View v) {
|
populateServers();
|
||||||
if(showingTabs) {
|
} else {
|
||||||
populateServers();
|
populateTabs();
|
||||||
} else {
|
|
||||||
populateTabs();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
drawerHeaderToggle = (ImageView) drawerHeader.findViewById(R.id.header_select_image);
|
drawerHeaderToggle = drawerHeader.findViewById(R.id.header_select_image);
|
||||||
drawerServerName = (TextView) drawerHeader.findViewById(R.id.header_server_name);
|
drawerServerName = drawerHeader.findViewById(R.id.header_server_name);
|
||||||
drawerUserName = (TextView) drawerHeader.findViewById(R.id.header_user_name);
|
drawerUserName = drawerHeader.findViewById(R.id.header_user_name);
|
||||||
|
|
||||||
updateDrawerHeader();
|
updateDrawerHeader();
|
||||||
|
|
||||||
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
drawer = findViewById(R.id.drawer_layout);
|
||||||
|
|
||||||
// Pass in toolbar if it exists
|
// Pass in toolbar if it exists
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
Toolbar toolbar = findViewById(R.id.main_toolbar);
|
||||||
drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.common_appname, R.string.common_appname) {
|
drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.common_appname, R.string.common_appname) {
|
||||||
@Override
|
@Override
|
||||||
public void onDrawerClosed(View view) {
|
public void onDrawerClosed(View view) {
|
||||||
drawerIdle = true;
|
drawerIdle = true;
|
||||||
drawerOpen = false;
|
drawerOpen = false;
|
||||||
|
|
||||||
if(!showingTabs) {
|
if (!showingTabs) {
|
||||||
populateTabs();
|
populateTabs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,10 +299,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
public void onDrawerOpened(View view) {
|
public void onDrawerOpened(View view) {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
boolean downloadingVisible = downloadService != null && !downloadService.getBackgroundDownloads().isEmpty();
|
boolean downloadingVisible = downloadService != null && !downloadService.getBackgroundDownloads().isEmpty();
|
||||||
if(lastSelectedPosition == R.id.drawer_downloading) {
|
if (lastSelectedPosition == R.id.drawer_downloading) {
|
||||||
downloadingVisible = true;
|
downloadingVisible = true;
|
||||||
}
|
}
|
||||||
setDrawerItemVisible(R.id.drawer_downloading, downloadingVisible);
|
setDrawerItemVisible(downloadingVisible);
|
||||||
|
|
||||||
drawerIdle = true;
|
drawerIdle = true;
|
||||||
drawerOpen = true;
|
drawerOpen = true;
|
||||||
@ -336,24 +314,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
drawerIdle = false;
|
drawerIdle = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
drawer.setDrawerListener(drawerToggle);
|
drawer.addDrawerListener(drawerToggle);
|
||||||
drawerToggle.setDrawerIndicatorEnabled(true);
|
drawerToggle.setDrawerIndicatorEnabled(true);
|
||||||
|
|
||||||
drawer.setOnTouchListener(new View.OnTouchListener() {
|
drawer.setOnTouchListener((v, event) -> drawerIdle && currentFragment != null && currentFragment.getGestureDetector() != null && currentFragment.getGestureDetector().onTouchEvent(event));
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
|
||||||
if (drawerIdle && currentFragment != null && currentFragment.getGestureDetector() != null) {
|
|
||||||
return currentFragment.getGestureDetector().onTouchEvent(event);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check whether this is a tablet or not
|
// Check whether this is a tablet or not
|
||||||
secondaryContainer = findViewById(R.id.fragment_second_container);
|
secondaryContainer = findViewById(R.id.fragment_second_container);
|
||||||
if(secondaryContainer != null) {
|
|
||||||
primaryContainer = findViewById(R.id.fragment_container);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -362,7 +329,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
String[] ids = new String[backStack.size() + 1];
|
String[] ids = new String[backStack.size() + 1];
|
||||||
ids[0] = currentFragment.getTag();
|
ids[0] = currentFragment.getTag();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for(SubsonicFragment frag: backStack) {
|
for (SubsonicFragment frag : backStack) {
|
||||||
ids[i] = frag.getTag();
|
ids[i] = frag.getTag();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -370,21 +337,22 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE, backStack.size() + 1);
|
savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE, backStack.size() + 1);
|
||||||
savedInstanceState.putInt(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
savedInstanceState.putInt(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||||
super.onRestoreInstanceState(savedInstanceState);
|
super.onRestoreInstanceState(savedInstanceState);
|
||||||
int size = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE);
|
int size = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE);
|
||||||
String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK);
|
String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK);
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
currentFragment = (SubsonicFragment)fm.findFragmentByTag(ids[0]);
|
currentFragment = (SubsonicFragment) fm.findFragmentByTag(ids[0]);
|
||||||
currentFragment.setPrimaryFragment(true);
|
currentFragment.setPrimaryFragment(true);
|
||||||
currentFragment.setSupportTag(ids[0]);
|
currentFragment.setSupportTag(ids[0]);
|
||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
for(int i = 1; i < size; i++) {
|
for (int i = 1; i < size; i++) {
|
||||||
SubsonicFragment frag = (SubsonicFragment)fm.findFragmentByTag(ids[i]);
|
SubsonicFragment frag = (SubsonicFragment) fm.findFragmentByTag(ids[i]);
|
||||||
frag.setSupportTag(ids[i]);
|
frag.setSupportTag(ids[i]);
|
||||||
if(secondaryContainer != null) {
|
if (secondaryContainer != null) {
|
||||||
frag.setPrimaryFragment(false, true);
|
frag.setPrimaryFragment(false, true);
|
||||||
}
|
}
|
||||||
trans.hide(frag);
|
trans.hide(frag);
|
||||||
@ -393,7 +361,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
trans.commit();
|
trans.commit();
|
||||||
|
|
||||||
// Current fragment is hidden in secondaryContainer
|
// Current fragment is hidden in secondaryContainer
|
||||||
if(secondaryContainer == null && !currentFragment.isVisible()) {
|
if (secondaryContainer == null && !currentFragment.isVisible()) {
|
||||||
trans = getSupportFragmentManager().beginTransaction();
|
trans = getSupportFragmentManager().beginTransaction();
|
||||||
trans.remove(currentFragment);
|
trans.remove(currentFragment);
|
||||||
trans.commit();
|
trans.commit();
|
||||||
@ -404,7 +372,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
trans.commit();
|
trans.commit();
|
||||||
}
|
}
|
||||||
// Current fragment needs to be moved over to secondaryContainer
|
// Current fragment needs to be moved over to secondaryContainer
|
||||||
else if(secondaryContainer != null && secondaryContainer.findViewById(currentFragment.getRootId()) == null && backStack.size() > 0) {
|
else if (secondaryContainer != null && secondaryContainer.findViewById(currentFragment.getRootId()) == null && backStack.size() > 0) {
|
||||||
trans = getSupportFragmentManager().beginTransaction();
|
trans = getSupportFragmentManager().beginTransaction();
|
||||||
trans.remove(currentFragment);
|
trans.remove(currentFragment);
|
||||||
trans.show(backStack.get(backStack.size() - 1));
|
trans.show(backStack.get(backStack.size() - 1));
|
||||||
@ -419,9 +387,9 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastSelectedPosition = savedInstanceState.getInt(Constants.FRAGMENT_POSITION);
|
lastSelectedPosition = savedInstanceState.getInt(Constants.FRAGMENT_POSITION);
|
||||||
if(lastSelectedPosition != 0) {
|
if (lastSelectedPosition != 0) {
|
||||||
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
||||||
if(item != null) {
|
if (item != null) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,26 +405,27 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
MenuInflater menuInflater = getMenuInflater();
|
MenuInflater menuInflater = getMenuInflater();
|
||||||
SubsonicFragment currentFragment = getCurrentFragment();
|
SubsonicFragment currentFragment = getCurrentFragment();
|
||||||
if(currentFragment != null) {
|
if (currentFragment != null) {
|
||||||
try {
|
try {
|
||||||
SubsonicFragment fragment = getCurrentFragment();
|
SubsonicFragment fragment = getCurrentFragment();
|
||||||
fragment.setContext(this);
|
fragment.setContext(this);
|
||||||
fragment.onCreateOptionsMenu(menu, menuInflater);
|
fragment.onCreateOptionsMenu(menu, menuInflater);
|
||||||
|
|
||||||
if(isTouchscreen()) {
|
if (isTouchscreen()) {
|
||||||
menu.setGroupVisible(R.id.not_touchscreen, false);
|
menu.setGroupVisible(R.id.not_touchscreen, false);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error on creating options menu", e);
|
Log.w(TAG, "Error on creating options menu", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
|
if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
} else if(item.getItemId() == android.R.id.home) {
|
} else if (item.getItemId() == android.R.id.home) {
|
||||||
onBackPressed();
|
onBackPressed();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -464,22 +433,14 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
return getCurrentFragment().onOptionsItemSelected(item);
|
return getCurrentFragment().onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
||||||
boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN;
|
|
||||||
boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP;
|
|
||||||
boolean isVolumeAdjust = isVolumeDown || isVolumeUp;
|
|
||||||
|
|
||||||
return super.onKeyDown(keyCode, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(CharSequence title) {
|
public void setTitle(CharSequence title) {
|
||||||
if(title != null && getSupportActionBar() != null && !title.equals(getSupportActionBar().getTitle())) {
|
if (title != null && getSupportActionBar() != null && !title.equals(getSupportActionBar().getTitle())) {
|
||||||
getSupportActionBar().setTitle(title);
|
getSupportActionBar().setTitle(title);
|
||||||
recreateSpinner();
|
recreateSpinner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSubtitle(CharSequence title) {
|
public void setSubtitle(CharSequence title) {
|
||||||
getSupportActionBar().setSubtitle(title);
|
getSupportActionBar().setSubtitle(title);
|
||||||
}
|
}
|
||||||
@ -487,8 +448,8 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
int top = spinnerAdapter.getCount() - 1;
|
int top = spinnerAdapter.getCount() - 1;
|
||||||
if(position < top) {
|
if (position < top) {
|
||||||
for(int i = top; i > position && i >= 0; i--) {
|
for (int i = top; i > position && i >= 0; i--) {
|
||||||
removeCurrent();
|
removeCurrent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,17 +464,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
drawerList.getMenu().clear();
|
drawerList.getMenu().clear();
|
||||||
drawerList.inflateMenu(R.menu.drawer_navigation);
|
drawerList.inflateMenu(R.menu.drawer_navigation);
|
||||||
|
|
||||||
SharedPreferences prefs = Util.getPreferences(this);
|
|
||||||
boolean sharedEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SHARED_ENABLED, true) && !Util.isOffline(this);
|
|
||||||
|
|
||||||
MenuItem offlineMenuItem = drawerList.getMenu().findItem(R.id.drawer_offline);
|
MenuItem offlineMenuItem = drawerList.getMenu().findItem(R.id.drawer_offline);
|
||||||
if(Util.isOffline(this)) {
|
if (Util.isOffline(this)) {
|
||||||
if(lastSelectedPosition == 0 || lastSelectedPosition == R.id.drawer_library) {
|
if (lastSelectedPosition == 0 || lastSelectedPosition == R.id.drawer_library) {
|
||||||
String newFragment = Util.openToTab(this);
|
String newFragment = "Artist";
|
||||||
if(newFragment == null || "Library".equals(newFragment)) {
|
|
||||||
newFragment = "Artist";
|
|
||||||
}
|
|
||||||
|
|
||||||
lastSelectedPosition = getDrawerItemId(newFragment);
|
lastSelectedPosition = getDrawerItemId(newFragment);
|
||||||
drawerItemSelected(newFragment);
|
drawerItemSelected(newFragment);
|
||||||
}
|
}
|
||||||
@ -523,9 +477,9 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
offlineMenuItem.setTitle(R.string.main_offline);
|
offlineMenuItem.setTitle(R.string.main_offline);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lastSelectedPosition != 0) {
|
if (lastSelectedPosition != 0) {
|
||||||
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
||||||
if(item != null) {
|
if (item != null) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,14 +487,15 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
|
|
||||||
showingTabs = true;
|
showingTabs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateServers() {
|
private void populateServers() {
|
||||||
drawerList.getMenu().clear();
|
drawerList.getMenu().clear();
|
||||||
|
|
||||||
int serverCount = Util.getServerCount(this);
|
int serverCount = Util.getServerCount(this);
|
||||||
int activeServer = Util.getActiveServer(this);
|
int activeServer = Util.getActiveServer(this);
|
||||||
for(int i = 1; i <= serverCount; i++) {
|
for (int i = 1; i <= serverCount; i++) {
|
||||||
MenuItem item = drawerList.getMenu().add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_BASE + i, MENU_ITEM_SERVER_BASE + i, Util.getServerName(this, i));
|
MenuItem item = drawerList.getMenu().add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_BASE + i, MENU_ITEM_SERVER_BASE + i, Util.getServerName(this, i));
|
||||||
if(activeServer == i) {
|
if (activeServer == i) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,52 +504,40 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
|
|
||||||
showingTabs = false;
|
showingTabs = false;
|
||||||
}
|
}
|
||||||
private void setDrawerItemVisible(int id, boolean visible) {
|
|
||||||
MenuItem item = drawerList.getMenu().findItem(id);
|
private void setDrawerItemVisible(boolean visible) {
|
||||||
if(item != null) {
|
MenuItem item = drawerList.getMenu().findItem(R.id.drawer_downloading);
|
||||||
|
if (item != null) {
|
||||||
item.setVisible(visible);
|
item.setVisible(visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawerItemSelected(String fragmentType) {
|
void drawerItemSelected(String fragmentType) {
|
||||||
if(currentFragment != null) {
|
if (currentFragment != null) {
|
||||||
currentFragment.stopActionMode();
|
currentFragment.stopActionMode();
|
||||||
}
|
}
|
||||||
startFragmentActivity(fragmentType);
|
startFragmentActivity(fragmentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startFragmentActivity(String fragmentType) {
|
void startFragmentActivity(String fragmentType) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setClass(SubsonicActivity.this, SubsonicFragmentActivity.class);
|
intent.setClass(SubsonicActivity.this, SubsonicFragmentActivity.class);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
if(!"".equals(fragmentType)) {
|
if (!"".equals(fragmentType)) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
||||||
}
|
}
|
||||||
if(lastSelectedPosition != 0) {
|
if (lastSelectedPosition != 0) {
|
||||||
intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
||||||
}
|
}
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void exit() {
|
boolean onBackPressedSupport() {
|
||||||
if(((Object) this).getClass() != SubsonicFragmentActivity.class) {
|
if (drawerOpen) {
|
||||||
Intent intent = new Intent(this, SubsonicFragmentActivity.class);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
|
|
||||||
Util.startActivityWithoutTransition(this, intent);
|
|
||||||
} else {
|
|
||||||
finished = true;
|
|
||||||
this.stopService(new Intent(this, DownloadService.class));
|
|
||||||
this.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onBackPressedSupport() {
|
|
||||||
if(drawerOpen) {
|
|
||||||
drawer.closeDrawers();
|
drawer.closeDrawers();
|
||||||
return false;
|
return false;
|
||||||
} else if(backStack.size() > 0) {
|
} else if (backStack.size() > 0) {
|
||||||
removeCurrent();
|
removeCurrent();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -604,7 +547,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if(onBackPressedSupport()) {
|
if (onBackPressedSupport()) {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -613,12 +556,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
return this.currentFragment;
|
return this.currentFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceFragment(SubsonicFragment fragment, int tag) {
|
void replaceFragment(SubsonicFragment fragment, int tag) {
|
||||||
replaceFragment(fragment, tag, false);
|
replaceFragment(fragment, tag, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
|
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
|
||||||
SubsonicFragment oldFragment = currentFragment;
|
SubsonicFragment oldFragment = currentFragment;
|
||||||
if(currentFragment != null) {
|
if (currentFragment != null) {
|
||||||
currentFragment.setPrimaryFragment(false, secondaryContainer != null);
|
currentFragment.setPrimaryFragment(false, secondaryContainer != null);
|
||||||
}
|
}
|
||||||
backStack.add(currentFragment);
|
backStack.add(currentFragment);
|
||||||
@ -627,7 +571,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
currentFragment.setPrimaryFragment(true);
|
currentFragment.setPrimaryFragment(true);
|
||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
|
|
||||||
if(secondaryContainer == null || oldFragment.isAlwaysFullscreen() || currentFragment.isAlwaysStartFullscreen()) {
|
if (secondaryContainer == null || oldFragment.isAlwaysFullscreen() || currentFragment.isAlwaysStartFullscreen()) {
|
||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
||||||
trans.hide(oldFragment);
|
trans.hide(oldFragment);
|
||||||
@ -640,16 +584,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
|
|
||||||
// Check to see if you need to put on top of old left or not
|
// Check to see if you need to put on top of old left or not
|
||||||
if(backStack.size() > 1) {
|
if (backStack.size() > 1) {
|
||||||
// Move old right to left if there is a backstack already
|
// Move old right to left if there is a backstack already
|
||||||
SubsonicFragment newLeftFragment = backStack.get(backStack.size() - 1);
|
SubsonicFragment newLeftFragment = backStack.get(backStack.size() - 1);
|
||||||
if(replaceCurrent) {
|
|
||||||
// trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
|
||||||
}
|
|
||||||
trans.remove(newLeftFragment);
|
trans.remove(newLeftFragment);
|
||||||
|
|
||||||
// Only move right to left if replaceCurrent is false
|
// Only move right to left if replaceCurrent is false
|
||||||
if(!replaceCurrent) {
|
if (!replaceCurrent) {
|
||||||
SubsonicFragment oldLeftFragment = backStack.get(backStack.size() - 2);
|
SubsonicFragment oldLeftFragment = backStack.get(backStack.size() - 2);
|
||||||
oldLeftFragment.setSecondaryFragment(false);
|
oldLeftFragment.setSecondaryFragment(false);
|
||||||
// trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
// trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
||||||
@ -679,13 +620,14 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
recreateSpinner();
|
recreateSpinner();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeCurrent() {
|
public void removeCurrent() {
|
||||||
// Don't try to remove current if there is no backstack to remove from
|
// Don't try to remove current if there is no backstack to remove from
|
||||||
if(backStack.isEmpty()) {
|
if (backStack.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentFragment != null) {
|
if (currentFragment != null) {
|
||||||
currentFragment.setPrimaryFragment(false);
|
currentFragment.setPrimaryFragment(false);
|
||||||
}
|
}
|
||||||
SubsonicFragment oldFragment = currentFragment;
|
SubsonicFragment oldFragment = currentFragment;
|
||||||
@ -694,7 +636,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
currentFragment.setPrimaryFragment(true, false);
|
currentFragment.setPrimaryFragment(true, false);
|
||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
|
|
||||||
if(secondaryContainer == null || currentFragment.isAlwaysFullscreen() || oldFragment.isAlwaysStartFullscreen()) {
|
if (secondaryContainer == null || currentFragment.isAlwaysFullscreen() || oldFragment.isAlwaysStartFullscreen()) {
|
||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
|
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
|
||||||
trans.remove(oldFragment);
|
trans.remove(oldFragment);
|
||||||
@ -708,7 +650,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
trans.remove(oldFragment);
|
trans.remove(oldFragment);
|
||||||
|
|
||||||
// Only switch places if there is a backstack, otherwise primary container is correct
|
// Only switch places if there is a backstack, otherwise primary container is correct
|
||||||
if(backStack.size() > 0 && !backStack.get(backStack.size() - 1).isAlwaysFullscreen() && !currentFragment.isAlwaysStartFullscreen()) {
|
if (backStack.size() > 0 && !backStack.get(backStack.size() - 1).isAlwaysFullscreen() && !currentFragment.isAlwaysStartFullscreen()) {
|
||||||
trans.setCustomAnimations(0, 0, 0, 0);
|
trans.setCustomAnimations(0, 0, 0, 0);
|
||||||
// Add current left fragment to right side
|
// Add current left fragment to right side
|
||||||
trans.remove(currentFragment);
|
trans.remove(currentFragment);
|
||||||
@ -735,20 +677,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
recreateSpinner();
|
recreateSpinner();
|
||||||
}
|
}
|
||||||
public void replaceExistingFragment(SubsonicFragment fragment, int tag) {
|
|
||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
||||||
trans.remove(currentFragment);
|
|
||||||
trans.add(R.id.fragment_container, fragment, tag + "");
|
|
||||||
trans.commit();
|
|
||||||
|
|
||||||
currentFragment = fragment;
|
|
||||||
currentFragment.setPrimaryFragment(true);
|
|
||||||
supportInvalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
if(currentFragment != null) {
|
if (currentFragment != null) {
|
||||||
while(backStack.size() > 0) {
|
while (backStack.size() > 0) {
|
||||||
removeCurrent();
|
removeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,26 +691,26 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void recreateSpinner() {
|
void recreateSpinner() {
|
||||||
if(currentFragment == null || currentFragment.getTitle() == null) {
|
if (currentFragment == null || currentFragment.getTitle() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(spinnerAdapter == null || getSupportActionBar().getCustomView() == null) {
|
if (spinnerAdapter == null || getSupportActionBar().getCustomView() == null) {
|
||||||
createCustomActionBarView();
|
createCustomActionBarView();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(backStack.size() > 0) {
|
if (backStack.size() > 0) {
|
||||||
createCustomActionBarView();
|
createCustomActionBarView();
|
||||||
spinnerAdapter.clear();
|
spinnerAdapter.clear();
|
||||||
for(int i = 0; i < backStack.size(); i++) {
|
for (int i = 0; i < backStack.size(); i++) {
|
||||||
CharSequence title = backStack.get(i).getTitle();
|
CharSequence title = backStack.get(i).getTitle();
|
||||||
if(title != null) {
|
if (title != null) {
|
||||||
spinnerAdapter.add(title);
|
spinnerAdapter.add(title);
|
||||||
} else {
|
} else {
|
||||||
spinnerAdapter.add("null");
|
spinnerAdapter.add("null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(currentFragment.getTitle() != null) {
|
if (currentFragment.getTitle() != null) {
|
||||||
spinnerAdapter.add(currentFragment.getTitle());
|
spinnerAdapter.add(currentFragment.getTitle());
|
||||||
} else {
|
} else {
|
||||||
spinnerAdapter.add("null");
|
spinnerAdapter.add("null");
|
||||||
@ -788,7 +720,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||||
getSupportActionBar().setDisplayShowCustomEnabled(true);
|
getSupportActionBar().setDisplayShowCustomEnabled(true);
|
||||||
|
|
||||||
if(drawerToggle.isDrawerIndicatorEnabled()) {
|
if (drawerToggle.isDrawerIndicatorEnabled()) {
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
drawerToggle.setDrawerIndicatorEnabled(false);
|
drawerToggle.setDrawerIndicatorEnabled(false);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
@ -801,19 +733,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void restart() {
|
private void restart() {
|
||||||
restart(true);
|
|
||||||
}
|
|
||||||
protected void restart(boolean resumePosition) {
|
|
||||||
Intent intent = new Intent(this, this.getClass());
|
Intent intent = new Intent(this, this.getClass());
|
||||||
intent.putExtras(getIntent());
|
intent.putExtras(getIntent());
|
||||||
if(resumePosition) {
|
intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
||||||
intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition);
|
|
||||||
} else {
|
|
||||||
String fragmentType = Util.openToTab(this);
|
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
|
||||||
intent.putExtra(Constants.FRAGMENT_POSITION, getDrawerItemId(fragmentType));
|
|
||||||
}
|
|
||||||
finish();
|
finish();
|
||||||
Util.startActivityWithoutTransition(this, intent);
|
Util.startActivityWithoutTransition(this, intent);
|
||||||
}
|
}
|
||||||
@ -821,7 +744,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
private void applyTheme() {
|
private void applyTheme() {
|
||||||
theme = ThemeUtil.getTheme(this);
|
theme = ThemeUtil.getTheme(this);
|
||||||
|
|
||||||
if(theme != null && theme.indexOf("fullscreen") != -1) {
|
if (theme != null && theme.contains("fullscreen")) {
|
||||||
theme = theme.substring(0, theme.indexOf("_fullscreen"));
|
theme = theme.substring(0, theme.indexOf("_fullscreen"));
|
||||||
ThemeUtil.setTheme(this, theme);
|
ThemeUtil.setTheme(this, theme);
|
||||||
}
|
}
|
||||||
@ -829,9 +752,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
ThemeUtil.applyTheme(this, theme);
|
ThemeUtil.applyTheme(this, theme);
|
||||||
actionbarColored = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true);
|
actionbarColored = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyFullscreen() {
|
private void applyFullscreen() {
|
||||||
fullScreen = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_FULL_SCREEN, false);
|
fullScreen = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_FULL_SCREEN, false);
|
||||||
if(fullScreen ) {
|
if (fullScreen) {
|
||||||
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
@ -851,15 +775,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
return IMAGE_LOADER;
|
return IMAGE_LOADER;
|
||||||
}
|
}
|
||||||
public synchronized static ImageLoader getStaticImageLoader(Context context) {
|
|
||||||
if (IMAGE_LOADER == null) {
|
|
||||||
IMAGE_LOADER = new ImageLoader(context);
|
|
||||||
}
|
|
||||||
return IMAGE_LOADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownloadService getDownloadService() {
|
public DownloadService getDownloadService() {
|
||||||
if(finished) {
|
boolean finished = false;
|
||||||
|
if (finished) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,42 +794,35 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
|
|
||||||
final DownloadService downloadService = DownloadService.getInstance();
|
final DownloadService downloadService = DownloadService.getInstance();
|
||||||
if(downloadService != null && afterServiceAvailable.size() > 0) {
|
if (downloadService != null && afterServiceAvailable.size() > 0) {
|
||||||
for(Runnable runnable: afterServiceAvailable) {
|
for (Runnable runnable : afterServiceAvailable) {
|
||||||
handler.post(runnable);
|
handler.post(runnable);
|
||||||
}
|
}
|
||||||
afterServiceAvailable.clear();
|
afterServiceAvailable.clear();
|
||||||
}
|
}
|
||||||
return downloadService;
|
return downloadService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runWhenServiceAvailable(Runnable runnable) {
|
public void runWhenServiceAvailable(Runnable runnable) {
|
||||||
if(getDownloadService() != null) {
|
if (getDownloadService() != null) {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} else {
|
} else {
|
||||||
afterServiceAvailable.add(runnable);
|
afterServiceAvailable.add(runnable);
|
||||||
checkIfServiceAvailable();
|
checkIfServiceAvailable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkIfServiceAvailable() {
|
private void checkIfServiceAvailable() {
|
||||||
if(getDownloadService() == null) {
|
if (getDownloadService() == null) {
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(this::checkIfServiceAvailable, 50);
|
||||||
@Override
|
} else if (afterServiceAvailable.size() > 0) {
|
||||||
public void run() {
|
for (Runnable runnable : afterServiceAvailable) {
|
||||||
checkIfServiceAvailable();
|
|
||||||
}
|
|
||||||
}, 50);
|
|
||||||
} else if(afterServiceAvailable.size() > 0) {
|
|
||||||
for(Runnable runnable: afterServiceAvailable) {
|
|
||||||
handler.post(runnable);
|
handler.post(runnable);
|
||||||
}
|
}
|
||||||
afterServiceAvailable.clear();
|
afterServiceAvailable.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getThemeName() {
|
|
||||||
return theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTouchscreen() {
|
public boolean isTouchscreen() {
|
||||||
return touchscreen;
|
return touchscreen;
|
||||||
}
|
}
|
||||||
@ -918,11 +830,12 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
public void openNowPlaying() {
|
public void openNowPlaying() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeNowPlaying() {
|
public void closeNowPlaying() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActiveServer(int instance) {
|
private void setActiveServer(int instance) {
|
||||||
if (Util.getActiveServer(this) != instance) {
|
if (Util.getActiveServer(this) != instance) {
|
||||||
final DownloadService service = getDownloadService();
|
final DownloadService service = getDownloadService();
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
@ -937,12 +850,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
Util.setActiveServer(this, instance);
|
Util.setActiveServer(this, instance);
|
||||||
invalidate();
|
invalidate();
|
||||||
UserUtil.refreshCurrentUser(this, false, true);
|
UserUtil.refreshCurrentUser(this);
|
||||||
updateDrawerHeader();
|
updateDrawerHeader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void updateDrawerHeader() {
|
|
||||||
if(Util.isOffline(this)) {
|
private void updateDrawerHeader() {
|
||||||
|
if (Util.isOffline(this)) {
|
||||||
drawerServerName.setText(R.string.select_album_offline);
|
drawerServerName.setText(R.string.select_album_offline);
|
||||||
drawerUserName.setText("");
|
drawerUserName.setText("");
|
||||||
drawerHeader.setClickable(false);
|
drawerHeader.setClickable(false);
|
||||||
@ -955,7 +869,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleOffline() {
|
private void toggleOffline() {
|
||||||
boolean isOffline = Util.isOffline(this);
|
boolean isOffline = Util.isOffline(this);
|
||||||
Util.setOffline(this, !isOffline);
|
Util.setOffline(this, !isOffline);
|
||||||
invalidate();
|
invalidate();
|
||||||
@ -969,12 +883,12 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
drawer.closeDrawers();
|
drawer.closeDrawers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDrawerItemId(String fragmentType) {
|
int getDrawerItemId(String fragmentType) {
|
||||||
if(fragmentType == null) {
|
if (fragmentType == null) {
|
||||||
return R.id.drawer_library;
|
return R.id.drawer_library;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(fragmentType) {
|
switch (fragmentType) {
|
||||||
case "Artist":
|
case "Artist":
|
||||||
return R.id.drawer_library;
|
return R.id.drawer_library;
|
||||||
case "Playlist":
|
case "Playlist":
|
||||||
@ -1013,7 +927,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||||||
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.nullsum.audinaut", 0);
|
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.nullsum.audinaut", 0);
|
||||||
file = new File(Environment.getExternalStorageDirectory(), "audinaut-stacktrace.txt");
|
file = new File(Environment.getExternalStorageDirectory(), "audinaut-stacktrace.txt");
|
||||||
printWriter = new PrintWriter(file);
|
printWriter = new PrintWriter(file);
|
||||||
printWriter.println("Android API level: " + Build.VERSION.SDK);
|
|
||||||
printWriter.println("Subsonic version name: " + packageInfo.versionName);
|
printWriter.println("Subsonic version name: " + packageInfo.versionName);
|
||||||
printWriter.println("Subsonic version code: " + packageInfo.versionCode);
|
printWriter.println("Subsonic version code: " + packageInfo.versionCode);
|
||||||
printWriter.println();
|
printWriter.println();
|
||||||
|
@ -20,42 +20,28 @@ package net.nullsum.audinaut.activity;
|
|||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
|
|
||||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
||||||
|
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
|
||||||
import java.io.File;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
||||||
import net.nullsum.audinaut.domain.PlayerState;
|
import net.nullsum.audinaut.domain.PlayerState;
|
||||||
import net.nullsum.audinaut.fragments.DownloadFragment;
|
import net.nullsum.audinaut.fragments.DownloadFragment;
|
||||||
import net.nullsum.audinaut.fragments.NowPlayingFragment;
|
import net.nullsum.audinaut.fragments.NowPlayingFragment;
|
||||||
@ -66,8 +52,6 @@ import net.nullsum.audinaut.fragments.SelectPlaylistFragment;
|
|||||||
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
||||||
import net.nullsum.audinaut.updates.Updater;
|
import net.nullsum.audinaut.updates.Updater;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
@ -75,15 +59,16 @@ import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|||||||
import net.nullsum.audinaut.util.UserUtil;
|
import net.nullsum.audinaut.util.UserUtil;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Scott on 10/14/13.
|
* Created by Scott on 10/14/13.
|
||||||
*/
|
*/
|
||||||
public class SubsonicFragmentActivity extends SubsonicActivity implements DownloadService.OnSongChangedListener {
|
public class SubsonicFragmentActivity extends SubsonicActivity implements DownloadService.OnSongChangedListener {
|
||||||
private static String TAG = SubsonicFragmentActivity.class.getSimpleName();
|
private static final String TAG = SubsonicFragmentActivity.class.getSimpleName();
|
||||||
private static boolean infoDialogDisplayed;
|
private static boolean infoDialogDisplayed;
|
||||||
private static boolean sessionInitialized = false;
|
private static boolean sessionInitialized = false;
|
||||||
private static long ALLOWED_SKEW = 30000L;
|
|
||||||
|
|
||||||
private SlidingUpPanelLayout slideUpPanel;
|
private SlidingUpPanelLayout slideUpPanel;
|
||||||
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
|
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
|
||||||
private boolean isPanelClosing = false;
|
private boolean isPanelClosing = false;
|
||||||
@ -97,9 +82,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
private TextView trackView;
|
private TextView trackView;
|
||||||
private TextView artistView;
|
private TextView artistView;
|
||||||
private ImageButton startButton;
|
private ImageButton startButton;
|
||||||
private long lastBackPressTime = 0;
|
|
||||||
private DownloadFile currentPlaying;
|
private DownloadFile currentPlaying;
|
||||||
private PlayerState currentState;
|
|
||||||
private ImageButton previousButton;
|
private ImageButton previousButton;
|
||||||
private ImageButton nextButton;
|
private ImageButton nextButton;
|
||||||
private ImageButton rewindButton;
|
private ImageButton rewindButton;
|
||||||
@ -107,14 +90,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
if(savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
||||||
boolean firstRun = false;
|
boolean firstRun = false;
|
||||||
if (fragmentType == null) {
|
if (fragmentType == null) {
|
||||||
fragmentType = Util.openToTab(this);
|
fragmentType = "Library";
|
||||||
if (fragmentType != null) {
|
firstRun = true;
|
||||||
firstRun = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("".equals(fragmentType) || fragmentType == null || firstRun) {
|
if ("".equals(fragmentType) || fragmentType == null || firstRun) {
|
||||||
@ -130,7 +111,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
stopService(new Intent(this, DownloadService.class));
|
stopService(new Intent(this, DownloadService.class));
|
||||||
finish();
|
finish();
|
||||||
getImageLoader().clearCache();
|
getImageLoader().clearCache();
|
||||||
} else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
|
} else if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
|
||||||
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Download");
|
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Download");
|
||||||
lastSelectedPosition = R.id.drawer_downloading;
|
lastSelectedPosition = R.id.drawer_downloading;
|
||||||
}
|
}
|
||||||
@ -138,17 +119,13 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
|
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
|
||||||
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
||||||
if(fragmentType == null) {
|
if (fragmentType == null) {
|
||||||
fragmentType = Util.openToTab(this);
|
fragmentType = "Library";
|
||||||
if(fragmentType != null) {
|
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
||||||
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
lastSelectedPosition = getDrawerItemId(fragmentType);
|
||||||
lastSelectedPosition = getDrawerItemId(fragmentType);
|
|
||||||
} else {
|
|
||||||
lastSelectedPosition = R.id.drawer_library;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
||||||
if(item != null) {
|
if (item != null) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -156,9 +133,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentFragment = getNewFragment(fragmentType);
|
currentFragment = getNewFragment(fragmentType);
|
||||||
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ID)) {
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ID)) {
|
||||||
Bundle currentArguments = currentFragment.getArguments();
|
Bundle currentArguments = currentFragment.getArguments();
|
||||||
if(currentArguments == null) {
|
if (currentArguments == null) {
|
||||||
currentArguments = new Bundle();
|
currentArguments = new Bundle();
|
||||||
}
|
}
|
||||||
currentArguments.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
currentArguments.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
||||||
@ -167,14 +144,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
currentFragment.setPrimaryFragment(true);
|
currentFragment.setPrimaryFragment(true);
|
||||||
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
||||||
|
|
||||||
if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
if (getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
||||||
SearchFragment fragment = new SearchFragment();
|
SearchFragment fragment = new SearchFragment();
|
||||||
replaceFragment(fragment, fragment.getSupportTag());
|
replaceFragment(fragment, fragment.getSupportTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a album type is set, switch to that album type view
|
// If a album type is set, switch to that album type view
|
||||||
String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
|
String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
|
||||||
if(albumType != null) {
|
if (albumType != null) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
@ -187,7 +164,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slideUpPanel = (SlidingUpPanelLayout) findViewById(R.id.slide_up_panel);
|
slideUpPanel = findViewById(R.id.slide_up_panel);
|
||||||
panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() {
|
panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPanelSlide(View panel, float slideOffset) {
|
public void onPanelSlide(View panel, float slideOffset) {
|
||||||
@ -198,7 +175,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) {
|
public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) {
|
||||||
if (newState == PanelState.COLLAPSED) {
|
if (newState == PanelState.COLLAPSED) {
|
||||||
isPanelClosing = false;
|
isPanelClosing = false;
|
||||||
if(bottomBar.getVisibility() == View.GONE) {
|
if (bottomBar.getVisibility() == View.GONE) {
|
||||||
bottomBar.setVisibility(View.VISIBLE);
|
bottomBar.setVisibility(View.VISIBLE);
|
||||||
nowPlayingToolbar.setVisibility(View.GONE);
|
nowPlayingToolbar.setVisibility(View.GONE);
|
||||||
nowPlayingFragment.setPrimaryFragment(false);
|
nowPlayingFragment.setPrimaryFragment(false);
|
||||||
@ -217,7 +194,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
nowPlayingToolbar.setVisibility(View.VISIBLE);
|
nowPlayingToolbar.setVisibility(View.VISIBLE);
|
||||||
setSupportActionBar(nowPlayingToolbar);
|
setSupportActionBar(nowPlayingToolbar);
|
||||||
|
|
||||||
if(secondaryFragment == null) {
|
if (secondaryFragment == null) {
|
||||||
nowPlayingFragment.setPrimaryFragment(true);
|
nowPlayingFragment.setPrimaryFragment(true);
|
||||||
} else {
|
} else {
|
||||||
secondaryFragment.setPrimaryFragment(true);
|
secondaryFragment.setPrimaryFragment(true);
|
||||||
@ -230,24 +207,19 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
};
|
};
|
||||||
slideUpPanel.addPanelSlideListener(panelSlideListener);
|
slideUpPanel.addPanelSlideListener(panelSlideListener);
|
||||||
|
|
||||||
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
|
||||||
// Post this later so it actually runs
|
// Post this later so it actually runs
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(this::openNowPlaying, 200);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
openNowPlaying();
|
|
||||||
}
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD);
|
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomBar = findViewById(R.id.bottom_bar);
|
bottomBar = findViewById(R.id.bottom_bar);
|
||||||
mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
mainToolbar = findViewById(R.id.main_toolbar);
|
||||||
nowPlayingToolbar = (Toolbar) findViewById(R.id.now_playing_toolbar);
|
nowPlayingToolbar = findViewById(R.id.now_playing_toolbar);
|
||||||
coverArtView = (ImageView) bottomBar.findViewById(R.id.album_art);
|
coverArtView = bottomBar.findViewById(R.id.album_art);
|
||||||
trackView = (TextView) bottomBar.findViewById(R.id.track_name);
|
trackView = bottomBar.findViewById(R.id.track_name);
|
||||||
artistView = (TextView) bottomBar.findViewById(R.id.artist_name);
|
artistView = bottomBar.findViewById(R.id.artist_name);
|
||||||
|
|
||||||
setSupportActionBar(mainToolbar);
|
setSupportActionBar(mainToolbar);
|
||||||
|
|
||||||
@ -258,97 +230,72 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
trans.commit();
|
trans.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
rewindButton = (ImageButton) findViewById(R.id.download_rewind);
|
rewindButton = findViewById(R.id.download_rewind);
|
||||||
rewindButton.setOnClickListener(new View.OnClickListener() {
|
rewindButton.setOnClickListener(v -> new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
if (getDownloadService() == null) {
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
}
|
||||||
if (getDownloadService() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDownloadService().rewind();
|
getDownloadService().rewind();
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
}.execute());
|
||||||
|
|
||||||
previousButton = (ImageButton) findViewById(R.id.download_previous);
|
previousButton = findViewById(R.id.download_previous);
|
||||||
previousButton.setOnClickListener(new View.OnClickListener() {
|
previousButton.setOnClickListener(v -> new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
if (getDownloadService() == null) {
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
}
|
||||||
if(getDownloadService() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDownloadService().previous();
|
getDownloadService().previous();
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
}.execute());
|
||||||
|
|
||||||
startButton = (ImageButton) findViewById(R.id.download_start);
|
startButton = findViewById(R.id.download_start);
|
||||||
startButton.setOnClickListener(new View.OnClickListener() {
|
startButton.setOnClickListener(v -> new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
PlayerState state = getDownloadService().getPlayerState();
|
||||||
@Override
|
if (state == PlayerState.STARTED) {
|
||||||
protected Void doInBackground() throws Throwable {
|
getDownloadService().pause();
|
||||||
PlayerState state = getDownloadService().getPlayerState();
|
} else {
|
||||||
if(state == PlayerState.STARTED) {
|
getDownloadService().start();
|
||||||
getDownloadService().pause();
|
}
|
||||||
} else {
|
|
||||||
getDownloadService().start();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
}.execute());
|
||||||
|
|
||||||
nextButton = (ImageButton) findViewById(R.id.download_next);
|
nextButton = findViewById(R.id.download_next);
|
||||||
nextButton.setOnClickListener(new View.OnClickListener() {
|
nextButton.setOnClickListener(v -> new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
if (getDownloadService() == null) {
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
}
|
||||||
if(getDownloadService() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDownloadService().next();
|
getDownloadService().next();
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
}.execute());
|
||||||
|
|
||||||
fastforwardButton = (ImageButton) findViewById(R.id.download_fastforward);
|
fastforwardButton = findViewById(R.id.download_fastforward);
|
||||||
fastforwardButton.setOnClickListener(new View.OnClickListener() {
|
fastforwardButton.setOnClickListener(v -> new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
if (getDownloadService() == null) {
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
}
|
||||||
if (getDownloadService() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDownloadService().fastForward();
|
getDownloadService().fastForward();
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
}.execute());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -363,17 +310,17 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
public void onNewIntent(Intent intent) {
|
public void onNewIntent(Intent intent) {
|
||||||
super.onNewIntent(intent);
|
super.onNewIntent(intent);
|
||||||
|
|
||||||
if(currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
if (currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
closeNowPlaying();
|
closeNowPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentFragment instanceof SearchFragment) {
|
if (currentFragment instanceof SearchFragment) {
|
||||||
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
||||||
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
|
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
|
||||||
|
|
||||||
if (query != null) {
|
if (query != null) {
|
||||||
((SearchFragment)currentFragment).search(query, autoplay);
|
((SearchFragment) currentFragment).search(query, autoplay);
|
||||||
}
|
}
|
||||||
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
||||||
} else {
|
} else {
|
||||||
@ -382,17 +329,17 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
SearchFragment fragment = new SearchFragment();
|
SearchFragment fragment = new SearchFragment();
|
||||||
replaceFragment(fragment, fragment.getSupportTag());
|
replaceFragment(fragment, fragment.getSupportTag());
|
||||||
}
|
}
|
||||||
} else if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, false)) {
|
} else if (intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, false)) {
|
||||||
if(slideUpPanel.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
openNowPlaying();
|
openNowPlaying();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
closeNowPlaying();
|
closeNowPlaying();
|
||||||
}
|
}
|
||||||
setIntent(intent);
|
setIntent(intent);
|
||||||
}
|
}
|
||||||
if(drawer != null) {
|
if (drawer != null) {
|
||||||
drawer.closeDrawers();
|
drawer.closeDrawers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,16 +348,16 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
if(getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) {
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME));
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME));
|
||||||
args.putString(Constants.INTENT_EXTRA_SEARCH_SONG, getIntent().getStringExtra(Constants.INTENT_EXTRA_SEARCH_SONG));
|
args.putString(Constants.INTENT_EXTRA_SEARCH_SONG, getIntent().getStringExtra(Constants.INTENT_EXTRA_SEARCH_SONG));
|
||||||
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ARTIST)) {
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ARTIST)) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
}
|
}
|
||||||
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)) {
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)) {
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID));
|
args.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID));
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
@ -421,19 +368,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
UserUtil.seedCurrentUser(this);
|
UserUtil.seedCurrentUser(this);
|
||||||
createAccount();
|
createAccount();
|
||||||
runWhenServiceAvailable(new Runnable() {
|
runWhenServiceAvailable(() -> getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService != null) {
|
if (downloadService != null) {
|
||||||
downloadService.removeOnSongChangeListener(this);
|
downloadService.removeOnSongChangeListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,11 +384,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
public void onSaveInstanceState(Bundle savedInstanceState) {
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
||||||
super.onSaveInstanceState(savedInstanceState);
|
super.onSaveInstanceState(savedInstanceState);
|
||||||
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag());
|
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag());
|
||||||
if(secondaryFragment != null) {
|
if (secondaryFragment != null) {
|
||||||
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING_SECONDARY, secondaryFragment.getTag());
|
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING_SECONDARY, secondaryFragment.getTag());
|
||||||
}
|
}
|
||||||
savedInstanceState.putInt(Constants.MAIN_SLIDE_PANEL_STATE, slideUpPanel.getPanelState().hashCode());
|
savedInstanceState.putInt(Constants.MAIN_SLIDE_PANEL_STATE, slideUpPanel.getPanelState().hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||||
super.onRestoreInstanceState(savedInstanceState);
|
super.onRestoreInstanceState(savedInstanceState);
|
||||||
@ -456,7 +399,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id);
|
nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id);
|
||||||
|
|
||||||
String secondaryId = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING_SECONDARY);
|
String secondaryId = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING_SECONDARY);
|
||||||
if(secondaryId != null) {
|
if (secondaryId != null) {
|
||||||
secondaryFragment = (SubsonicFragment) fm.findFragmentByTag(secondaryId);
|
secondaryFragment = (SubsonicFragment) fm.findFragmentByTag(secondaryId);
|
||||||
|
|
||||||
nowPlayingFragment.setPrimaryFragment(false);
|
nowPlayingFragment.setPrimaryFragment(false);
|
||||||
@ -467,11 +410,11 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
trans.commit();
|
trans.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(drawerToggle != null && backStack.size() > 0) {
|
if (drawerToggle != null && backStack.size() > 0) {
|
||||||
drawerToggle.setDrawerIndicatorEnabled(false);
|
drawerToggle.setDrawerIndicatorEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) {
|
if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) {
|
||||||
panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED);
|
panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,28 +422,23 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
@Override
|
@Override
|
||||||
public void setContentView(int viewId) {
|
public void setContentView(int viewId) {
|
||||||
super.setContentView(viewId);
|
super.setContentView(viewId);
|
||||||
if(drawerToggle != null){
|
if (drawerToggle != null) {
|
||||||
drawerToggle.setDrawerIndicatorEnabled(true);
|
drawerToggle.setDrawerIndicatorEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment == null) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment == null) {
|
||||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
||||||
} else if(onBackPressedSupport()) {
|
} else if (onBackPressedSupport()) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBackPressedSupport() {
|
boolean onBackPressedSupport() {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
removeCurrent();
|
removeCurrent();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -510,8 +448,8 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubsonicFragment getCurrentFragment() {
|
public SubsonicFragment getCurrentFragment() {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
if(secondaryFragment == null) {
|
if (secondaryFragment == null) {
|
||||||
return nowPlayingFragment;
|
return nowPlayingFragment;
|
||||||
} else {
|
} else {
|
||||||
return secondaryFragment;
|
return secondaryFragment;
|
||||||
@ -523,7 +461,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
|
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
|
||||||
if(slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) {
|
if (slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) {
|
||||||
secondaryFragment = fragment;
|
secondaryFragment = fragment;
|
||||||
nowPlayingFragment.setPrimaryFragment(false);
|
nowPlayingFragment.setPrimaryFragment(false);
|
||||||
secondaryFragment.setPrimaryFragment(true);
|
secondaryFragment.setPrimaryFragment(true);
|
||||||
@ -538,9 +476,10 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
super.replaceFragment(fragment, tag, replaceCurrent);
|
super.replaceFragment(fragment, tag, replaceCurrent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCurrent() {
|
public void removeCurrent() {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment != null) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment != null) {
|
||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
|
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
|
||||||
trans.remove(secondaryFragment);
|
trans.remove(secondaryFragment);
|
||||||
@ -557,7 +496,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(CharSequence title) {
|
public void setTitle(CharSequence title) {
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
getSupportActionBar().setTitle(title);
|
getSupportActionBar().setTitle(title);
|
||||||
} else {
|
} else {
|
||||||
super.setTitle(title);
|
super.setTitle(title);
|
||||||
@ -568,7 +507,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
protected void drawerItemSelected(String fragmentType) {
|
protected void drawerItemSelected(String fragmentType) {
|
||||||
super.drawerItemSelected(fragmentType);
|
super.drawerItemSelected(fragmentType);
|
||||||
|
|
||||||
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,7 +518,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
||||||
|
|
||||||
// Clear existing stack
|
// Clear existing stack
|
||||||
for(int i = backStack.size() - 1; i >= 0; i--) {
|
for (int i = backStack.size() - 1; i >= 0; i--) {
|
||||||
trans.remove(backStack.get(i));
|
trans.remove(backStack.get(i));
|
||||||
}
|
}
|
||||||
trans.remove(currentFragment);
|
trans.remove(currentFragment);
|
||||||
@ -594,14 +533,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
trans.commit();
|
trans.commit();
|
||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
recreateSpinner();
|
recreateSpinner();
|
||||||
if(drawer != null) {
|
if (drawer != null) {
|
||||||
drawer.closeDrawers();
|
drawer.closeDrawers();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(secondaryContainer != null) {
|
if (secondaryContainer != null) {
|
||||||
secondaryContainer.setVisibility(View.GONE);
|
secondaryContainer.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
if(drawerToggle != null) {
|
if (drawerToggle != null) {
|
||||||
drawerToggle.setDrawerIndicatorEnabled(true);
|
drawerToggle.setDrawerIndicatorEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,6 +549,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
public void openNowPlaying() {
|
public void openNowPlaying() {
|
||||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeNowPlaying() {
|
public void closeNowPlaying() {
|
||||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
||||||
@ -617,25 +557,24 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SubsonicFragment getNewFragment(String fragmentType) {
|
private SubsonicFragment getNewFragment(String fragmentType) {
|
||||||
if("Artist".equals(fragmentType)) {
|
if ("Artist".equals(fragmentType)) {
|
||||||
return new SelectArtistFragment();
|
return new SelectArtistFragment();
|
||||||
} else if("Playlist".equals(fragmentType)) {
|
} else if ("Playlist".equals(fragmentType)) {
|
||||||
return new SelectPlaylistFragment();
|
return new SelectPlaylistFragment();
|
||||||
} else if("Download".equals(fragmentType)) {
|
} else if ("Download".equals(fragmentType)) {
|
||||||
return new DownloadFragment();
|
return new DownloadFragment();
|
||||||
} else {
|
} else {
|
||||||
return new SelectArtistFragment();
|
return new SelectArtistFragment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkUpdates() {
|
private void checkUpdates() {
|
||||||
try {
|
try {
|
||||||
String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
|
String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
|
||||||
int ver = Integer.parseInt(version.replace(".", ""));
|
int ver = Integer.parseInt(version.replace(".", ""));
|
||||||
Updater updater = new Updater(ver);
|
Updater updater = new Updater(ver);
|
||||||
updater.checkUpdates(this);
|
updater.checkUpdates(this);
|
||||||
}
|
} catch (Exception ignored) {
|
||||||
catch(Exception e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,12 +582,13 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
private void loadSession() {
|
private void loadSession() {
|
||||||
loadSettings();
|
loadSettings();
|
||||||
// If we are on Subsonic 5.2+, save play queue
|
// If we are on Subsonic 5.2+, save play queue
|
||||||
if(!Util.isOffline(this)) {
|
if (!Util.isOffline(this)) {
|
||||||
loadRemotePlayQueue();
|
loadRemotePlayQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionInitialized = true;
|
sessionInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSettings() {
|
private void loadSettings() {
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.settings_appearance, false);
|
PreferenceManager.setDefaultValues(this, R.xml.settings_appearance, false);
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.settings_cache, false);
|
PreferenceManager.setDefaultValues(this, R.xml.settings_cache, false);
|
||||||
@ -660,9 +600,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
} else {
|
} else {
|
||||||
String path = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
String path = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
File cacheLocation = new File(path);
|
File cacheLocation = new File(path);
|
||||||
if(!FileUtil.verifyCanWrite(cacheLocation)) {
|
if (!FileUtil.verifyCanWrite(cacheLocation)) {
|
||||||
// Only warn user if there is a difference saved
|
// Only warn user if there is a difference saved
|
||||||
if(resetCacheLocation(prefs)) {
|
if (resetCacheLocation(prefs)) {
|
||||||
Util.info(this, R.string.common_warning, R.string.settings_cache_location_reset);
|
Util.info(this, R.string.common_warning, R.string.settings_cache_location_reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,7 +619,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
if(!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) {
|
if (!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1);
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
@ -689,7 +629,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
private boolean resetCacheLocation(SharedPreferences prefs) {
|
private boolean resetCacheLocation(SharedPreferences prefs) {
|
||||||
String newDirectory = FileUtil.getDefaultMusicDirectory(this).getPath();
|
String newDirectory = FileUtil.getDefaultMusicDirectory(this).getPath();
|
||||||
String oldDirectory = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
String oldDirectory = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
if(newDirectory == null || (oldDirectory != null && newDirectory.equals(oldDirectory))) {
|
if (newDirectory == null || (oldDirectory != null && newDirectory.equals(oldDirectory))) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
@ -700,36 +640,20 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadRemotePlayQueue() {
|
private void loadRemotePlayQueue() {
|
||||||
if(Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER, false)) {
|
if (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER, false)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final SubsonicActivity context = this;
|
|
||||||
new SilentBackgroundTask<Void>(this) {
|
new SilentBackgroundTask<Void>(this) {
|
||||||
private PlayerQueue playerQueue;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
|
||||||
PlayerQueue remoteState = musicService.getPlayQueue(context, null);
|
|
||||||
|
|
||||||
// Make sure we wait until download service is ready
|
// Make sure we wait until download service is ready
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
while(downloadService == null || !downloadService.isInitialized()) {
|
while (downloadService == null || !downloadService.isInitialized()) {
|
||||||
Util.sleepQuietly(100L);
|
Util.sleepQuietly(100L);
|
||||||
downloadService = getDownloadService();
|
downloadService = getDownloadService();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we had a remote state and it's changed is more recent than our existing state
|
|
||||||
if(remoteState != null && remoteState.changed != null) {
|
|
||||||
// Check if changed + 30 seconds since some servers have slight skew
|
|
||||||
Date remoteChange = new Date(remoteState.changed.getTime() - ALLOWED_SKEW);
|
|
||||||
Date localChange = downloadService.getLastStateChanged();
|
|
||||||
if(localChange == null || localChange.before(remoteChange)) {
|
|
||||||
playerQueue = remoteState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to get playing queue to server", e);
|
Log.e(TAG, "Failed to get playing queue to server", e);
|
||||||
}
|
}
|
||||||
@ -759,27 +683,18 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showInfoDialog() {
|
private void showInfoDialog() {
|
||||||
if (!infoDialogDisplayed) {
|
if (!infoDialogDisplayed) {
|
||||||
infoDialogDisplayed = true;
|
infoDialogDisplayed = true;
|
||||||
if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) {
|
if (Util.getRestUrl(this).contains("demo.subsonic.org")) {
|
||||||
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
|
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Toolbar getActiveToolbar() {
|
|
||||||
return slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED ? nowPlayingToolbar : mainToolbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex) {
|
public void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex) {
|
||||||
this.currentPlaying = currentPlaying;
|
this.currentPlaying = currentPlaying;
|
||||||
@ -789,7 +704,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
song = currentPlaying.getSong();
|
song = currentPlaying.getSong();
|
||||||
trackView.setText(song.getTitle());
|
trackView.setText(song.getTitle());
|
||||||
|
|
||||||
if(song.getArtist() != null) {
|
if (song.getArtist() != null) {
|
||||||
artistView.setVisibility(View.VISIBLE);
|
artistView.setVisibility(View.VISIBLE);
|
||||||
artistView.setText(song.getArtist());
|
artistView.setText(song.getArtist());
|
||||||
} else {
|
} else {
|
||||||
@ -820,7 +735,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSongsChanged(List<DownloadFile> songs, DownloadFile currentPlaying, int currentPlayingIndex) {
|
public void onSongsChanged(List<DownloadFile> songs, DownloadFile currentPlaying, int currentPlayingIndex) {
|
||||||
if(this.currentPlaying != currentPlaying || this.currentPlaying == null) {
|
if (this.currentPlaying != currentPlaying || this.currentPlaying == null) {
|
||||||
onSongChanged(currentPlaying, currentPlayingIndex);
|
onSongChanged(currentPlaying, currentPlayingIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,7 +746,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStateUpdate(DownloadFile downloadFile, PlayerState playerState) {
|
public void onStateUpdate(PlayerState playerState) {
|
||||||
int[] attrs = new int[]{(playerState == PlayerState.STARTED) ? R.attr.actionbar_pause : R.attr.actionbar_start};
|
int[] attrs = new int[]{(playerState == PlayerState.STARTED) ? R.attr.actionbar_pause : R.attr.actionbar_start};
|
||||||
TypedArray typedArray = this.obtainStyledAttributes(attrs);
|
TypedArray typedArray = this.obtainStyledAttributes(attrs);
|
||||||
startButton.setImageResource(typedArray.getResourceId(0, 0));
|
startButton.setImageResource(typedArray.getResourceId(0, 0));
|
||||||
@ -840,7 +755,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMetadataUpdate(MusicDirectory.Entry song, int fieldChange) {
|
public void onMetadataUpdate(MusicDirectory.Entry song, int fieldChange) {
|
||||||
if(song != null && coverArtView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
|
if (song != null && coverArtView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
|
||||||
int height = coverArtView.getHeight();
|
int height = coverArtView.getHeight();
|
||||||
if (height <= 0) {
|
if (height <= 0) {
|
||||||
int[] attrs = new int[]{R.attr.actionBarSize};
|
int[] attrs = new int[]{R.attr.actionBarSize};
|
||||||
@ -851,7 +766,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||||||
getImageLoader().loadImage(coverArtView, song, false, height, false);
|
getImageLoader().loadImage(coverArtView, song, false, height, false);
|
||||||
|
|
||||||
// We need to update it immediately since it won't update if updater is not running for it
|
// We need to update it immediately since it won't update if updater is not running for it
|
||||||
if(nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
|
if (nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
|
||||||
nowPlayingFragment.onMetadataUpdate(song, fieldChange);
|
nowPlayingFragment.onMetadataUpdate(song, fieldChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,23 +24,18 @@ import android.app.SearchManager;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.provider.SearchRecentSuggestions;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.provider.AudinautSearchProvider;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives voice search queries and forwards to the SearchFragment.
|
* Receives voice search queries and forwards to the SearchFragment.
|
||||||
*
|
* <p>
|
||||||
* http://android-developers.blogspot.com/2010/09/supporting-new-music-voice-action.html
|
* http://android-developers.blogspot.com/2010/09/supporting-new-music-voice-action.html
|
||||||
*
|
*
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class VoiceQueryReceiverActivity extends Activity {
|
public class VoiceQueryReceiverActivity extends Activity {
|
||||||
private static final String TAG = VoiceQueryReceiverActivity.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -57,6 +52,5 @@ public class VoiceQueryReceiverActivity extends Activity {
|
|||||||
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
Util.disablePendingTransition(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,12 @@ package net.nullsum.audinaut.adapter;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
import net.nullsum.audinaut.util.ImageLoader;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter {
|
public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter {
|
||||||
public AlphabeticalAlbumAdapter(Context context, List<MusicDirectory.Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
public AlphabeticalAlbumAdapter(Context context, List<MusicDirectory.Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
||||||
super(context, entries, imageLoader, largeCell);
|
super(context, entries, imageLoader, largeCell);
|
||||||
@ -31,8 +31,8 @@ public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implement
|
|||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
// Make sure that we are not trying to get an item for the loading placeholder
|
// Make sure that we are not trying to get an item for the loading placeholder
|
||||||
if(position >= sections.get(0).size()) {
|
if (position >= sections.get(0).size()) {
|
||||||
if(sections.get(0).size() > 0) {
|
if (sections.get(0).size() > 0) {
|
||||||
return getTextToShowInBubble(position - 1);
|
return getTextToShowInBubble(position - 1);
|
||||||
} else {
|
} else {
|
||||||
return "*";
|
return "*";
|
||||||
|
@ -18,17 +18,12 @@ package net.nullsum.audinaut.adapter;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v7.widget.PopupMenu;
|
import android.support.v7.widget.PopupMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
@ -37,16 +32,14 @@ import net.nullsum.audinaut.view.FastScroller;
|
|||||||
import net.nullsum.audinaut.view.SongView;
|
import net.nullsum.audinaut.view.SongView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ArtistAdapter extends SectionAdapter<Serializable> implements FastScroller.BubbleTextGetter {
|
public class ArtistAdapter extends SectionAdapter<Serializable> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_SONG = 3;
|
public static final int VIEW_TYPE_ARTIST = 4;
|
||||||
public static int VIEW_TYPE_ARTIST = 4;
|
private static final int VIEW_TYPE_SONG = 3;
|
||||||
|
private final List<MusicFolder> musicFolders;
|
||||||
private List<MusicFolder> musicFolders;
|
private final OnMusicFolderChanged onMusicFolderChanged;
|
||||||
private OnMusicFolderChanged onMusicFolderChanged;
|
|
||||||
|
|
||||||
public ArtistAdapter(Context context, List<Serializable> artists, OnItemClickedListener listener) {
|
|
||||||
this(context, artists, null, listener, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtistAdapter(Context context, List<Serializable> artists, List<MusicFolder> musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) {
|
public ArtistAdapter(Context context, List<Serializable> artists, List<MusicFolder> musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) {
|
||||||
super(context, artists);
|
super(context, artists);
|
||||||
@ -54,7 +47,7 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
this.onMusicFolderChanged = onMusicFolderChanged;
|
this.onMusicFolderChanged = onMusicFolderChanged;
|
||||||
|
|
||||||
if(musicFolders != null) {
|
if (musicFolders != null) {
|
||||||
this.singleSectionHeader = true;
|
this.singleSectionHeader = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,46 +55,41 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false);
|
final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false);
|
||||||
header.setOnClickListener(new View.OnClickListener() {
|
header.setOnClickListener(v -> {
|
||||||
@Override
|
PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2));
|
||||||
public void onClick(View v) {
|
|
||||||
PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2));
|
|
||||||
|
|
||||||
popup.getMenu().add(R.string.select_artist_all_folders);
|
popup.getMenu().add(R.string.select_artist_all_folders);
|
||||||
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
|
popup.getMenu().add(musicFolder.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.setOnMenuItemClickListener(item -> {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
popup.getMenu().add(musicFolder.getName());
|
if (item.getTitle().equals(musicFolder.getName())) {
|
||||||
}
|
if (onMusicFolderChanged != null) {
|
||||||
|
onMusicFolderChanged.onMusicFolderChanged(musicFolder);
|
||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
|
||||||
if(item.getTitle().equals(musicFolder.getName())) {
|
|
||||||
if(onMusicFolderChanged != null) {
|
|
||||||
onMusicFolderChanged.onMusicFolderChanged(musicFolder);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(onMusicFolderChanged != null) {
|
|
||||||
onMusicFolderChanged.onMusicFolderChanged(null);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
popup.show();
|
|
||||||
}
|
if (onMusicFolderChanged != null) {
|
||||||
|
onMusicFolderChanged.onMusicFolderChanged(null);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
popup.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
return new UpdateView.UpdateViewHolder(header, false);
|
return new UpdateView.UpdateViewHolder(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
TextView folderName = (TextView) holder.getView().findViewById(R.id.select_artist_folder_2);
|
TextView folderName = holder.getView().findViewById(R.id.select_artist_folder_2);
|
||||||
|
|
||||||
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
if(musicFolderId != null) {
|
if (musicFolderId != null) {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
if (musicFolder.getId().equals(musicFolderId)) {
|
if (musicFolder.getId().equals(musicFolderId)) {
|
||||||
folderName.setText(musicFolder.getName());
|
folderName.setText(musicFolder.getName());
|
||||||
@ -114,11 +102,11 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ARTIST) {
|
if (viewType == VIEW_TYPE_ARTIST) {
|
||||||
updateView = new ArtistView(context);
|
updateView = new ArtistView(context);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,9 +116,9 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ARTIST) {
|
if (viewType == VIEW_TYPE_ARTIST) {
|
||||||
view.setObject(item);
|
view.setObject(item);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
Entry entry = (Entry) item;
|
Entry entry = (Entry) item;
|
||||||
songView.setObject(entry, checkable);
|
songView.setObject(entry, checkable);
|
||||||
@ -139,7 +127,7 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Serializable item) {
|
public int getItemViewType(Serializable item) {
|
||||||
if(item instanceof Artist) {
|
if (item instanceof Artist) {
|
||||||
return VIEW_TYPE_ARTIST;
|
return VIEW_TYPE_ARTIST;
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_SONG;
|
return VIEW_TYPE_SONG;
|
||||||
@ -149,7 +137,7 @@ public class ArtistAdapter extends SectionAdapter<Serializable> implements FastS
|
|||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
Object item = getItemForPosition(position);
|
Object item = getItemForPosition(position);
|
||||||
if(item instanceof Artist) {
|
if (item instanceof Artist) {
|
||||||
return getNameIndex(((Artist) item).getName(), true);
|
return getNameIndex(((Artist) item).getName(), true);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -16,15 +16,14 @@
|
|||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.view.BasicListView;
|
import net.nullsum.audinaut.view.BasicListView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class BasicListAdapter extends SectionAdapter<String> {
|
public class BasicListAdapter extends SectionAdapter<String> {
|
||||||
public static int VIEW_TYPE_LINE = 1;
|
private static final int VIEW_TYPE_LINE = 1;
|
||||||
|
|
||||||
public BasicListAdapter(Context context, List<String> strings, OnItemClickedListener listener) {
|
public BasicListAdapter(Context context, List<String> strings, OnItemClickedListener listener) {
|
||||||
super(context, strings);
|
super(context, strings);
|
||||||
@ -32,7 +31,7 @@ public class BasicListAdapter extends SectionAdapter<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicListView(context));
|
return new UpdateView.UpdateViewHolder(new BasicListView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.method.LinkMovementMethod;
|
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -25,32 +23,32 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class DetailsAdapter extends ArrayAdapter<String> {
|
import java.util.List;
|
||||||
private List<String> headers;
|
|
||||||
private List<String> details;
|
|
||||||
|
|
||||||
public DetailsAdapter(Context context, int layout, List<String> headers, List<String> details) {
|
public class DetailsAdapter extends ArrayAdapter<String> {
|
||||||
super(context, layout, headers);
|
private final List<String> headers;
|
||||||
|
private final List<String> details;
|
||||||
|
|
||||||
|
public DetailsAdapter(Context context, List<String> headers, List<String> details) {
|
||||||
|
super(context, R.layout.details_item, headers);
|
||||||
|
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.details = details;
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent){
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
View view;
|
View view;
|
||||||
if(convertView == null) {
|
if (convertView == null) {
|
||||||
view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null);
|
view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null);
|
||||||
} else {
|
} else {
|
||||||
view = convertView;
|
view = convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView nameView = (TextView) view.findViewById(R.id.detail_name);
|
TextView nameView = view.findViewById(R.id.detail_name);
|
||||||
TextView detailsView = (TextView) view.findViewById(R.id.detail_value);
|
TextView detailsView = view.findViewById(R.id.detail_value);
|
||||||
|
|
||||||
nameView.setText(headers.get(position));
|
nameView.setText(headers.get(position));
|
||||||
|
|
||||||
|
@ -18,12 +18,6 @@ package net.nullsum.audinaut.adapter;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
@ -32,8 +26,10 @@ import net.nullsum.audinaut.view.FastScroller;
|
|||||||
import net.nullsum.audinaut.view.SongView;
|
import net.nullsum.audinaut.view.SongView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements FastScroller.BubbleTextGetter {
|
public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_DOWNLOAD_FILE = 1;
|
private static final int VIEW_TYPE_DOWNLOAD_FILE = 1;
|
||||||
|
|
||||||
public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
|
public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
|
||||||
super(context, entries);
|
super(context, entries);
|
||||||
@ -42,7 +38,7 @@ public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new SongView(context));
|
return new UpdateView.UpdateViewHolder(new SongView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +61,7 @@ public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_nowplaying, menu);
|
menuInflater.inflate(R.menu.multiselect_nowplaying, menu);
|
||||||
|
@ -18,11 +18,6 @@ package net.nullsum.audinaut.adapter;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
@ -34,19 +29,17 @@ import net.nullsum.audinaut.view.SongView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class EntryGridAdapter extends SectionAdapter<Entry> {
|
public class EntryGridAdapter extends SectionAdapter<Entry> {
|
||||||
private static String TAG = EntryGridAdapter.class.getSimpleName();
|
public static final int VIEW_TYPE_ALBUM_CELL = 1;
|
||||||
|
public static final int VIEW_TYPE_ALBUM_LINE = 2;
|
||||||
public static int VIEW_TYPE_ALBUM_CELL = 1;
|
public static final int VIEW_TYPE_SONG = 3;
|
||||||
public static int VIEW_TYPE_ALBUM_LINE = 2;
|
private final ImageLoader imageLoader;
|
||||||
public static int VIEW_TYPE_SONG = 3;
|
private final boolean largeAlbums;
|
||||||
|
|
||||||
private ImageLoader imageLoader;
|
|
||||||
private boolean largeAlbums;
|
|
||||||
private boolean showArtist = false;
|
private boolean showArtist = false;
|
||||||
private boolean showAlbum = false;
|
private boolean showAlbum = false;
|
||||||
private boolean removeFromPlaylist = false;
|
private boolean removeFromPlaylist = false;
|
||||||
private View header;
|
|
||||||
|
|
||||||
public EntryGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
public EntryGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
||||||
super(context, entries);
|
super(context, entries);
|
||||||
@ -55,12 +48,12 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
|
|||||||
|
|
||||||
// Always show artist if they aren't all the same
|
// Always show artist if they aren't all the same
|
||||||
String artist = null;
|
String artist = null;
|
||||||
for(MusicDirectory.Entry entry: entries) {
|
for (MusicDirectory.Entry entry : entries) {
|
||||||
if(artist == null) {
|
if (artist == null) {
|
||||||
artist = entry.getArtist();
|
artist = entry.getArtist();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(artist != null && !artist.equals(entry.getArtist())) {
|
if (artist != null && !artist.equals(entry.getArtist())) {
|
||||||
showArtist = true;
|
showArtist = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,11 +61,11 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) {
|
if (viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) {
|
||||||
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,27 +75,24 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) {
|
public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
AlbumView albumView = (AlbumView) view;
|
AlbumView albumView = (AlbumView) view;
|
||||||
albumView.setShowArtist(showArtist);
|
albumView.setShowArtist(showArtist);
|
||||||
albumView.setObject(entry, imageLoader);
|
albumView.setObject(entry, imageLoader);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
songView.setShowAlbum(showAlbum);
|
songView.setShowAlbum(showAlbum);
|
||||||
songView.setObject(entry, checkable);
|
songView.setObject(entry, checkable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
|
||||||
return new UpdateViewHolder(header, false);
|
|
||||||
}
|
|
||||||
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Entry entry) {
|
public int getItemViewType(Entry entry) {
|
||||||
if(entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
if (largeAlbums) {
|
if (largeAlbums) {
|
||||||
return VIEW_TYPE_ALBUM_CELL;
|
return VIEW_TYPE_ALBUM_CELL;
|
||||||
} else {
|
} else {
|
||||||
@ -113,27 +103,16 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(View header) {
|
public void setShowArtist() {
|
||||||
this.header = header;
|
this.showArtist = true;
|
||||||
this.singleSectionHeader = true;
|
|
||||||
}
|
|
||||||
public View getHeader() {
|
|
||||||
return header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowArtist(boolean showArtist) {
|
public void setShowAlbum() {
|
||||||
this.showArtist = showArtist;
|
this.showAlbum = true;
|
||||||
}
|
|
||||||
|
|
||||||
public void setShowAlbum(boolean showAlbum) {
|
|
||||||
this.showAlbum = showAlbum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAt(int index) {
|
public void removeAt(int index) {
|
||||||
sections.get(0).remove(index);
|
sections.get(0).remove(index);
|
||||||
if(header != null) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
notifyItemRemoved(index);
|
notifyItemRemoved(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,13 +122,13 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_media, menu);
|
menuInflater.inflate(R.menu.multiselect_media, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!removeFromPlaylist) {
|
if (!removeFromPlaylist) {
|
||||||
menu.removeItem(R.id.menu_remove_playlist);
|
menu.removeItem(R.id.menu_remove_playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
@ -32,8 +30,10 @@ import net.nullsum.audinaut.util.ImageLoader;
|
|||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
||||||
public static int VIEW_TYPE_LOADING = 4;
|
public static final int VIEW_TYPE_LOADING = 4;
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
private String extra;
|
private String extra;
|
||||||
@ -48,10 +48,10 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if(viewType == VIEW_TYPE_LOADING) {
|
if (viewType == VIEW_TYPE_LOADING) {
|
||||||
View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null);
|
View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null);
|
||||||
progress.setVisibility(View.VISIBLE);
|
progress.setVisibility(View.VISIBLE);
|
||||||
return new UpdateView.UpdateViewHolder(progress, false);
|
return new UpdateView.UpdateViewHolder(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onCreateViewHolder(parent, viewType);
|
return super.onCreateViewHolder(parent, viewType);
|
||||||
@ -59,7 +59,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if(isLoadingView(position)) {
|
if (isLoadingView(position)) {
|
||||||
return VIEW_TYPE_LOADING;
|
return VIEW_TYPE_LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) {
|
||||||
if(!isLoadingView(position)) {
|
if (!isLoadingView(position)) {
|
||||||
super.onBindViewHolder(holder, position);
|
super.onBindViewHolder(holder, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
int size = super.getItemCount();
|
int size = super.getItemCount();
|
||||||
|
|
||||||
if(!allLoaded) {
|
if (!allLoaded) {
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,13 +89,13 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
this.extra = extra;
|
this.extra = extra;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|
||||||
if(super.getItemCount() < size) {
|
if (super.getItemCount() < size) {
|
||||||
allLoaded = true;
|
allLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMore() {
|
public void loadMore() {
|
||||||
if(loading || allLoaded) {
|
if (loading || allLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loading = true;
|
loading = true;
|
||||||
@ -114,7 +114,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
appendCachedData(newData);
|
appendCachedData(newData);
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
if(newData.size() < size) {
|
if (newData.size() < size) {
|
||||||
allLoaded = true;
|
allLoaded = true;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@ -122,15 +122,15 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Entry> cacheInBackground() throws Exception {
|
private List<Entry> cacheInBackground() throws Exception {
|
||||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||||
MusicDirectory result;
|
MusicDirectory result;
|
||||||
int offset = sections.get(0).size();
|
int offset = sections.get(0).size();
|
||||||
if("genres".equals(type) || "years".equals(type)) {
|
if ("genres".equals(type) || "years".equals(type)) {
|
||||||
result = service.getAlbumList(type, extra, size, offset, false, context, null);
|
result = service.getAlbumList(type, extra, size, offset, false, context, null);
|
||||||
} else if("genres".equals(type) || "genres-songs".equals(type)) {
|
} else if ("genres".equals(type) || "genres-songs".equals(type)) {
|
||||||
result = service.getSongsByGenre(extra, size, offset, context, null);
|
result = service.getSongsByGenre(extra, size, offset, context, null);
|
||||||
}else if(type.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
|
} else if (type.contains(MainFragment.SONGS_LIST_PREFIX)) {
|
||||||
result = service.getSongList(type, size, offset, context, null);
|
result = service.getSongList(type, size, offset, context, null);
|
||||||
} else {
|
} else {
|
||||||
result = service.getAlbumList(type, size, offset, false, context, null);
|
result = service.getAlbumList(type, size, offset, false, context, null);
|
||||||
@ -138,15 +138,15 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
|||||||
return result.getChildren();
|
return result.getChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void appendCachedData(List<Entry> newData) {
|
private void appendCachedData(List<Entry> newData) {
|
||||||
if(newData.size() > 0) {
|
if (newData.size() > 0) {
|
||||||
int start = sections.get(0).size();
|
int start = sections.get(0).size();
|
||||||
sections.get(0).addAll(newData);
|
sections.get(0).addAll(newData);
|
||||||
this.notifyItemRangeInserted(start, newData.size());
|
this.notifyItemRangeInserted(start, newData.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isLoadingView(int position) {
|
private boolean isLoadingView(int position) {
|
||||||
return !allLoaded && position >= sections.get(0).size();
|
return !allLoaded && position >= sections.get(0).size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,51 +16,34 @@
|
|||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.util.DrawableTint;
|
import net.nullsum.audinaut.util.DrawableTint;
|
||||||
import net.nullsum.audinaut.view.BasicHeaderView;
|
import net.nullsum.audinaut.view.BasicHeaderView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
import java.util.ArrayList;
|
||||||
private static final String TAG = ExpandableSectionAdapter.class.getSimpleName();
|
import java.util.List;
|
||||||
|
|
||||||
|
abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
||||||
private static final int DEFAULT_VISIBLE = 4;
|
private static final int DEFAULT_VISIBLE = 4;
|
||||||
private static final int EXPAND_TOGGLE = R.attr.select_server;
|
private static final int EXPAND_TOGGLE = R.attr.select_server;
|
||||||
private static final int COLLAPSE_TOGGLE = R.attr.select_tabs;
|
private static final int COLLAPSE_TOGGLE = R.attr.select_tabs;
|
||||||
|
|
||||||
protected List<Integer> sectionsDefaultVisible;
|
private List<List<T>> sectionsExtras;
|
||||||
protected List<List<T>> sectionsExtras;
|
|
||||||
protected int expandToggleRes;
|
|
||||||
protected int collapseToggleRes;
|
|
||||||
|
|
||||||
protected ExpandableSectionAdapter() {}
|
ExpandableSectionAdapter() {
|
||||||
public ExpandableSectionAdapter(Context context, List<T> section) {
|
}
|
||||||
List<List<T>> sections = new ArrayList<>();
|
|
||||||
sections.add(section);
|
|
||||||
|
|
||||||
init(context, Arrays.asList("Section"), sections, Arrays.asList((Integer) null));
|
void init(Context context, List<String> headers, List<List<T>> fullSections, List<Integer> sectionsDefaultVisible) {
|
||||||
}
|
|
||||||
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
|
||||||
init(context, headers, sections, null);
|
|
||||||
}
|
|
||||||
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections, List<Integer> sectionsDefaultVisible) {
|
|
||||||
init(context, headers, sections, sectionsDefaultVisible);
|
|
||||||
}
|
|
||||||
protected void init(Context context, List<String> headers, List<List<T>> fullSections, List<Integer> sectionsDefaultVisible) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.sectionsDefaultVisible = sectionsDefaultVisible;
|
if (sectionsDefaultVisible == null) {
|
||||||
if(sectionsDefaultVisible == null) {
|
|
||||||
sectionsDefaultVisible = new ArrayList<>(fullSections.size());
|
sectionsDefaultVisible = new ArrayList<>(fullSections.size());
|
||||||
for(int i = 0; i < fullSections.size(); i++) {
|
for (int i = 0; i < fullSections.size(); i++) {
|
||||||
sectionsDefaultVisible.add(DEFAULT_VISIBLE);
|
sectionsDefaultVisible.add(DEFAULT_VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,11 +51,11 @@ public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
|||||||
this.sections = new ArrayList<>();
|
this.sections = new ArrayList<>();
|
||||||
this.sectionsExtras = new ArrayList<>();
|
this.sectionsExtras = new ArrayList<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(List<T> fullSection: fullSections) {
|
for (List<T> fullSection : fullSections) {
|
||||||
List<T> visibleSection = new ArrayList<>();
|
List<T> visibleSection = new ArrayList<>();
|
||||||
|
|
||||||
Integer defaultVisible = sectionsDefaultVisible.get(i);
|
Integer defaultVisible = sectionsDefaultVisible.get(i);
|
||||||
if(defaultVisible == null || defaultVisible >= fullSection.size()) {
|
if (defaultVisible == null || defaultVisible >= fullSection.size()) {
|
||||||
visibleSection.addAll(fullSection);
|
visibleSection.addAll(fullSection);
|
||||||
this.sectionsExtras.add(null);
|
this.sectionsExtras.add(null);
|
||||||
} else {
|
} else {
|
||||||
@ -83,9 +66,6 @@ public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
|||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
expandToggleRes = DrawableTint.getDrawableRes(context, EXPAND_TOGGLE);
|
|
||||||
collapseToggleRes = DrawableTint.getDrawableRes(context, COLLAPSE_TOGGLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -96,39 +76,36 @@ public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
|||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, final int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, final int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
ImageView toggleSelectionView = (ImageView) view.findViewById(R.id.item_select);
|
ImageView toggleSelectionView = view.findViewById(R.id.item_select);
|
||||||
|
|
||||||
List<T> visibleSelection = sections.get(sectionIndex);
|
List<T> visibleSelection = sections.get(sectionIndex);
|
||||||
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
||||||
|
|
||||||
if(sectionExtras != null && !sectionExtras.isEmpty()) {
|
if (sectionExtras != null && !sectionExtras.isEmpty()) {
|
||||||
toggleSelectionView.setVisibility(View.VISIBLE);
|
toggleSelectionView.setVisibility(View.VISIBLE);
|
||||||
toggleSelectionView.setOnClickListener(new View.OnClickListener() {
|
toggleSelectionView.setOnClickListener(v -> {
|
||||||
@Override
|
List<T> visibleSelection1 = sections.get(sectionIndex);
|
||||||
public void onClick(View v) {
|
List<T> sectionExtras1 = sectionsExtras.get(sectionIndex);
|
||||||
List<T> visibleSelection = sections.get(sectionIndex);
|
|
||||||
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
|
||||||
|
|
||||||
// Update icon
|
// Update icon
|
||||||
int selectToggleAttr;
|
int selectToggleAttr;
|
||||||
if (!visibleSelection.contains(sectionExtras.get(0))) {
|
if (!visibleSelection1.contains(sectionExtras1.get(0))) {
|
||||||
selectToggleAttr = COLLAPSE_TOGGLE;
|
selectToggleAttr = COLLAPSE_TOGGLE;
|
||||||
|
|
||||||
// Update how many are displayed
|
// Update how many are displayed
|
||||||
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
int lastIndex = getItemPosition(visibleSelection1.get(visibleSelection1.size() - 1));
|
||||||
visibleSelection.addAll(sectionExtras);
|
visibleSelection1.addAll(sectionExtras1);
|
||||||
notifyItemRangeInserted(lastIndex, sectionExtras.size());
|
notifyItemRangeInserted(lastIndex, sectionExtras1.size());
|
||||||
} else {
|
} else {
|
||||||
selectToggleAttr = EXPAND_TOGGLE;
|
selectToggleAttr = EXPAND_TOGGLE;
|
||||||
|
|
||||||
// Update how many are displayed
|
// Update how many are displayed
|
||||||
visibleSelection.removeAll(sectionExtras);
|
visibleSelection1.removeAll(sectionExtras1);
|
||||||
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
int lastIndex = getItemPosition(visibleSelection1.get(visibleSelection1.size() - 1));
|
||||||
notifyItemRangeRemoved(lastIndex, sectionExtras.size());
|
notifyItemRangeRemoved(lastIndex, sectionExtras1.size());
|
||||||
}
|
|
||||||
|
|
||||||
((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
||||||
});
|
});
|
||||||
|
|
||||||
int selectToggleAttr;
|
int selectToggleAttr;
|
||||||
@ -143,7 +120,7 @@ public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
|||||||
toggleSelectionView.setVisibility(View.GONE);
|
toggleSelectionView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(view != null) {
|
if (view != null) {
|
||||||
view.setObject(header);
|
view.setObject(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
import net.nullsum.audinaut.view.GenreView;
|
import net.nullsum.audinaut.view.GenreView;
|
||||||
@ -24,8 +24,8 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GenreAdapter extends SectionAdapter<Genre> implements FastScroller.BubbleTextGetter{
|
public class GenreAdapter extends SectionAdapter<Genre> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_GENRE = 1;
|
private static final int VIEW_TYPE_GENRE = 1;
|
||||||
|
|
||||||
public GenreAdapter(Context context, List<Genre> genres, OnItemClickedListener listener) {
|
public GenreAdapter(Context context, List<Genre> genres, OnItemClickedListener listener) {
|
||||||
super(context, genres);
|
super(context, genres);
|
||||||
@ -33,7 +33,7 @@ public class GenreAdapter extends SectionAdapter<Genre> implements FastScroller.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new GenreView(context));
|
return new UpdateView.UpdateViewHolder(new GenreView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,18 +19,16 @@ import android.content.Context;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
import net.nullsum.audinaut.view.BasicHeaderView;
|
import net.nullsum.audinaut.view.BasicHeaderView;
|
||||||
import net.nullsum.audinaut.view.BasicListView;
|
import net.nullsum.audinaut.view.BasicListView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MainAdapter extends SectionAdapter<Integer> {
|
public class MainAdapter extends SectionAdapter<Integer> {
|
||||||
public static final int VIEW_TYPE_ALBUM_LIST = 1;
|
private static final int VIEW_TYPE_ALBUM_LIST = 1;
|
||||||
|
|
||||||
public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) {
|
public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) {
|
||||||
super(context, headers, sections);
|
super(context, headers, sections);
|
||||||
@ -38,7 +36,7 @@ public class MainAdapter extends SectionAdapter<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
UpdateView updateView = new BasicListView(context);
|
UpdateView updateView = new BasicListView(context);
|
||||||
return new UpdateView.UpdateViewHolder(updateView);
|
return new UpdateView.UpdateViewHolder(updateView);
|
||||||
}
|
}
|
||||||
@ -47,7 +45,7 @@ public class MainAdapter extends SectionAdapter<Integer> {
|
|||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) {
|
||||||
UpdateView updateView = holder.getUpdateView();
|
UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(viewType == VIEW_TYPE_ALBUM_LIST) {
|
if (viewType == VIEW_TYPE_ALBUM_LIST) {
|
||||||
updateView.setObject(context.getResources().getString(item));
|
updateView.setObject(context.getResources().getString(item));
|
||||||
} else {
|
} else {
|
||||||
updateView.setObject(item);
|
updateView.setObject(item);
|
||||||
@ -63,13 +61,14 @@ public class MainAdapter extends SectionAdapter<Integer> {
|
|||||||
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header));
|
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox);
|
CheckBox checkBox = view.findViewById(R.id.item_checkbox);
|
||||||
|
|
||||||
String display;
|
String display;
|
||||||
if("songs".equals(header)) {
|
if ("songs".equals(header)) {
|
||||||
display = context.getResources().getString(R.string.search_songs);
|
display = context.getResources().getString(R.string.search_songs);
|
||||||
checkBox.setVisibility(View.GONE);
|
checkBox.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
@ -77,7 +76,7 @@ public class MainAdapter extends SectionAdapter<Integer> {
|
|||||||
checkBox.setVisibility(View.GONE);
|
checkBox.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(view != null) {
|
if (view != null) {
|
||||||
view.setObject(display);
|
view.setObject(display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,20 +16,19 @@ package net.nullsum.audinaut.adapter;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
import net.nullsum.audinaut.util.ImageLoader;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
import net.nullsum.audinaut.view.PlaylistView;
|
import net.nullsum.audinaut.view.PlaylistView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScroller.BubbleTextGetter {
|
import java.util.List;
|
||||||
public static int VIEW_TYPE_PLAYLIST = 1;
|
|
||||||
|
|
||||||
private ImageLoader imageLoader;
|
public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScroller.BubbleTextGetter {
|
||||||
private boolean largeCell;
|
private static final int VIEW_TYPE_PLAYLIST = 1;
|
||||||
|
|
||||||
|
private final ImageLoader imageLoader;
|
||||||
|
private final boolean largeCell;
|
||||||
|
|
||||||
public PlaylistAdapter(Context context, List<Playlist> playlists, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
public PlaylistAdapter(Context context, List<Playlist> playlists, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
||||||
super(context, playlists);
|
super(context, playlists);
|
||||||
@ -37,15 +36,9 @@ public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScr
|
|||||||
this.largeCell = largeCell;
|
this.largeCell = largeCell;
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
}
|
}
|
||||||
public PlaylistAdapter(Context context, List<String> headers, List<List<Playlist>> sections, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
|
||||||
super(context, headers, sections);
|
|
||||||
this.imageLoader = imageLoader;
|
|
||||||
this.largeCell = largeCell;
|
|
||||||
this.onItemClickedListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new PlaylistView(context, imageLoader, largeCell));
|
return new UpdateView.UpdateViewHolder(new PlaylistView(context, imageLoader, largeCell));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +56,7 @@ public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScr
|
|||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
Object item = getItemForPosition(position);
|
Object item = getItemForPosition(position);
|
||||||
if(item instanceof Playlist) {
|
if (item instanceof Playlist) {
|
||||||
return getNameIndex(((Playlist) item).getName());
|
return getNameIndex(((Playlist) item).getName());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -19,38 +19,32 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
import net.nullsum.audinaut.domain.SearchResult;
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
import net.nullsum.audinaut.util.DrawableTint;
|
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
import net.nullsum.audinaut.util.ImageLoader;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.view.AlbumView;
|
import net.nullsum.audinaut.view.AlbumView;
|
||||||
import net.nullsum.audinaut.view.ArtistView;
|
import net.nullsum.audinaut.view.ArtistView;
|
||||||
import net.nullsum.audinaut.view.BasicHeaderView;
|
|
||||||
import net.nullsum.audinaut.view.SongView;
|
import net.nullsum.audinaut.view.SongView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static net.nullsum.audinaut.adapter.ArtistAdapter.VIEW_TYPE_ARTIST;
|
import static net.nullsum.audinaut.adapter.ArtistAdapter.VIEW_TYPE_ARTIST;
|
||||||
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_CELL;
|
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_CELL;
|
||||||
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_LINE;
|
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_LINE;
|
||||||
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_SONG;
|
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_SONG;
|
||||||
|
|
||||||
public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
||||||
private ImageLoader imageLoader;
|
|
||||||
private boolean largeAlbums;
|
|
||||||
|
|
||||||
private static final int MAX_ARTISTS = 10;
|
private static final int MAX_ARTISTS = 10;
|
||||||
private static final int MAX_ALBUMS = 4;
|
private static final int MAX_ALBUMS = 4;
|
||||||
private static final int MAX_SONGS = 10;
|
private static final int MAX_SONGS = 10;
|
||||||
|
private final ImageLoader imageLoader;
|
||||||
|
private final boolean largeAlbums;
|
||||||
|
|
||||||
public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) {
|
public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) {
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
@ -60,17 +54,17 @@ public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
|||||||
List<String> headers = new ArrayList<>();
|
List<String> headers = new ArrayList<>();
|
||||||
List<Integer> defaultVisible = new ArrayList<>();
|
List<Integer> defaultVisible = new ArrayList<>();
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
if(!searchResult.getArtists().isEmpty()) {
|
if (!searchResult.getArtists().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getArtists());
|
sections.add((List<Serializable>) (List<?>) searchResult.getArtists());
|
||||||
headers.add(res.getString(R.string.search_artists));
|
headers.add(res.getString(R.string.search_artists));
|
||||||
defaultVisible.add(MAX_ARTISTS);
|
defaultVisible.add(MAX_ARTISTS);
|
||||||
}
|
}
|
||||||
if(!searchResult.getAlbums().isEmpty()) {
|
if (!searchResult.getAlbums().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getAlbums());
|
sections.add((List<Serializable>) (List<?>) searchResult.getAlbums());
|
||||||
headers.add(res.getString(R.string.search_albums));
|
headers.add(res.getString(R.string.search_albums));
|
||||||
defaultVisible.add(MAX_ALBUMS);
|
defaultVisible.add(MAX_ALBUMS);
|
||||||
}
|
}
|
||||||
if(!searchResult.getSongs().isEmpty()) {
|
if (!searchResult.getSongs().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getSongs());
|
sections.add((List<Serializable>) (List<?>) searchResult.getSongs());
|
||||||
headers.add(res.getString(R.string.search_songs));
|
headers.add(res.getString(R.string.search_songs));
|
||||||
defaultVisible.add(MAX_SONGS);
|
defaultVisible.add(MAX_SONGS);
|
||||||
@ -82,13 +76,13 @@ public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
} else if(viewType == VIEW_TYPE_ARTIST) {
|
} else if (viewType == VIEW_TYPE_ARTIST) {
|
||||||
updateView = new ArtistView(context);
|
updateView = new ArtistView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,20 +92,20 @@ public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
AlbumView albumView = (AlbumView) view;
|
AlbumView albumView = (AlbumView) view;
|
||||||
albumView.setObject((Entry) item, imageLoader);
|
albumView.setObject((Entry) item, imageLoader);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if (viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
songView.setObject((Entry) item, true);
|
songView.setObject((Entry) item, true);
|
||||||
} else if(viewType == VIEW_TYPE_ARTIST) {
|
} else if (viewType == VIEW_TYPE_ARTIST) {
|
||||||
view.setObject(item);
|
view.setObject(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Serializable item) {
|
public int getItemViewType(Serializable item) {
|
||||||
if(item instanceof Entry) {
|
if (item instanceof Entry) {
|
||||||
Entry entry = (Entry) item;
|
Entry entry = (Entry) item;
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
if (largeAlbums) {
|
if (largeAlbums) {
|
||||||
@ -129,7 +123,7 @@ public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_media, menu);
|
menuInflater.inflate(R.menu.multiselect_media, menu);
|
||||||
|
@ -32,10 +32,6 @@ import android.view.Window;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
@ -45,129 +41,103 @@ import net.nullsum.audinaut.view.BasicHeaderView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewHolder<T>> {
|
public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewHolder<T>> {
|
||||||
private static String TAG = SectionAdapter.class.getSimpleName();
|
public static final int VIEW_TYPE_HEADER = 0;
|
||||||
public static int VIEW_TYPE_HEADER = 0;
|
private static final String TAG = SectionAdapter.class.getSimpleName();
|
||||||
public static String[] ignoredArticles;
|
private static String[] ignoredArticles;
|
||||||
|
private final List<T> selected = new ArrayList<>();
|
||||||
|
private final List<UpdateView> selectedViews = new ArrayList<>();
|
||||||
|
Context context;
|
||||||
|
List<String> headers;
|
||||||
|
List<List<T>> sections;
|
||||||
|
boolean singleSectionHeader;
|
||||||
|
OnItemClickedListener<T> onItemClickedListener;
|
||||||
|
boolean checkable = false;
|
||||||
|
private ActionMode currentActionMode;
|
||||||
|
|
||||||
protected Context context;
|
SectionAdapter() {
|
||||||
protected List<String> headers;
|
|
||||||
protected List<List<T>> sections;
|
|
||||||
protected boolean singleSectionHeader;
|
|
||||||
protected OnItemClickedListener<T> onItemClickedListener;
|
|
||||||
protected List<T> selected = new ArrayList<>();
|
|
||||||
protected List<UpdateView> selectedViews = new ArrayList<>();
|
|
||||||
protected ActionMode currentActionMode;
|
|
||||||
protected boolean checkable = false;
|
|
||||||
|
|
||||||
protected SectionAdapter() {}
|
|
||||||
public SectionAdapter(Context context, List<T> section) {
|
|
||||||
this(context, section, false);
|
|
||||||
}
|
}
|
||||||
public SectionAdapter(Context context, List<T> section, boolean singleSectionHeader) {
|
|
||||||
|
SectionAdapter(Context context, List<T> section) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = Arrays.asList("Section");
|
this.headers = Collections.singletonList("Section");
|
||||||
this.sections = new ArrayList<>();
|
this.sections = new ArrayList<>();
|
||||||
this.sections.add(section);
|
this.sections.add(section);
|
||||||
this.singleSectionHeader = singleSectionHeader;
|
this.singleSectionHeader = false;
|
||||||
}
|
}
|
||||||
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
|
||||||
this(context, headers, sections, true);
|
SectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
||||||
}
|
|
||||||
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections, boolean singleSectionHeader){
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.sections = sections;
|
this.sections = sections;
|
||||||
this.singleSectionHeader = singleSectionHeader;
|
this.singleSectionHeader = true;
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceExistingData(List<T> section) {
|
|
||||||
this.sections = new ArrayList<>();
|
|
||||||
this.sections.add(section);
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
public void replaceExistingData(List<String> headers, List<List<T>> sections) {
|
|
||||||
this.headers = headers;
|
|
||||||
this.sections = sections;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if(viewType == VIEW_TYPE_HEADER) {
|
if (viewType == VIEW_TYPE_HEADER) {
|
||||||
return onCreateHeaderHolder(parent);
|
return onCreateHeaderHolder(parent);
|
||||||
} else {
|
} else {
|
||||||
final UpdateViewHolder<T> holder = onCreateSectionViewHolder(parent, viewType);
|
final UpdateViewHolder<T> holder = onCreateSectionViewHolder(viewType);
|
||||||
final UpdateView updateView = holder.getUpdateView();
|
final UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(updateView != null) {
|
if (updateView != null) {
|
||||||
updateView.getChildAt(0).setOnClickListener(new View.OnClickListener() {
|
updateView.getChildAt(0).setOnClickListener(v -> {
|
||||||
@Override
|
T item = holder.getItem();
|
||||||
public void onClick(View v) {
|
if (currentActionMode != null) {
|
||||||
T item = holder.getItem();
|
if (updateView.isCheckable()) {
|
||||||
updateView.onClick();
|
if (selected.contains(item)) {
|
||||||
if (currentActionMode != null) {
|
selected.remove(item);
|
||||||
if(updateView.isCheckable()) {
|
selectedViews.remove(updateView);
|
||||||
if (selected.contains(item)) {
|
setChecked(updateView, false);
|
||||||
selected.remove(item);
|
} else {
|
||||||
selectedViews.remove(updateView);
|
selected.add(item);
|
||||||
setChecked(updateView, false);
|
selectedViews.add(updateView);
|
||||||
} else {
|
setChecked(updateView, true);
|
||||||
selected.add(item);
|
}
|
||||||
selectedViews.add(updateView);
|
|
||||||
setChecked(updateView, true);
|
if (selected.isEmpty()) {
|
||||||
}
|
currentActionMode.finish();
|
||||||
|
} else {
|
||||||
if (selected.isEmpty()) {
|
currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
||||||
currentActionMode.finish();
|
|
||||||
} else {
|
|
||||||
currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (onItemClickedListener != null) {
|
|
||||||
onItemClickedListener.onItemClicked(updateView, item);
|
|
||||||
}
|
}
|
||||||
|
} else if (onItemClickedListener != null) {
|
||||||
|
onItemClickedListener.onItemClicked(updateView, item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
View moreButton = updateView.findViewById(R.id.item_more);
|
View moreButton = updateView.findViewById(R.id.item_more);
|
||||||
if (moreButton != null) {
|
if (moreButton != null) {
|
||||||
moreButton.setOnClickListener(new View.OnClickListener() {
|
moreButton.setOnClickListener(v -> {
|
||||||
@Override
|
try {
|
||||||
public void onClick(View v) {
|
final T item = holder.getItem();
|
||||||
try {
|
if (onItemClickedListener != null) {
|
||||||
final T item = holder.getItem();
|
PopupMenu popup = new PopupMenu(context, v);
|
||||||
if (onItemClickedListener != null) {
|
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
||||||
PopupMenu popup = new PopupMenu(context, v);
|
|
||||||
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popup.setOnMenuItemClickListener(menuItem -> onItemClickedListener.onContextItemSelected(menuItem, updateView, item));
|
||||||
@Override
|
popup.show();
|
||||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
||||||
return onItemClickedListener.onContextItemSelected(menuItem, updateView, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
}
|
|
||||||
} catch(Exception e) {
|
|
||||||
Log.w(TAG, "Failed to show popup", e);
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Failed to show popup", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(checkable) {
|
if (checkable) {
|
||||||
updateView.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() {
|
updateView.getChildAt(0).setOnLongClickListener(v -> {
|
||||||
@Override
|
if (updateView.isCheckable()) {
|
||||||
public boolean onLongClick(View v) {
|
if (currentActionMode == null) {
|
||||||
if(updateView.isCheckable()) {
|
startActionMode(holder);
|
||||||
if (currentActionMode == null) {
|
} else {
|
||||||
startActionMode(holder);
|
updateView.getChildAt(0).performClick();
|
||||||
} else {
|
|
||||||
updateView.getChildAt(0).performClick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +151,7 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
public void onBindViewHolder(UpdateViewHolder holder, int position) {
|
public void onBindViewHolder(UpdateViewHolder holder, int position) {
|
||||||
UpdateView updateView = holder.getUpdateView();
|
UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if (sections.size() == 1 && !singleSectionHeader) {
|
||||||
T item = sections.get(0).get(position);
|
T item = sections.get(0).get(position);
|
||||||
onBindViewHolder(holder, item, getItemViewType(position));
|
onBindViewHolder(holder, item, getItemViewType(position));
|
||||||
postBindView(updateView, item);
|
postBindView(updateView, item);
|
||||||
@ -191,15 +161,15 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
int subHeader = 0;
|
int subHeader = 0;
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
boolean validHeader = headers.get(subHeader) != null;
|
boolean validHeader = headers.get(subHeader) != null;
|
||||||
if(position == subPosition && validHeader) {
|
if (position == subPosition && validHeader) {
|
||||||
onBindHeaderHolder(holder, headers.get(subHeader), subHeader);
|
onBindHeaderHolder(holder, headers.get(subHeader), subHeader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int headerOffset = validHeader ? 1 : 0;
|
int headerOffset = validHeader ? 1 : 0;
|
||||||
if(position < (subPosition + section.size() + headerOffset)) {
|
if (position < (subPosition + section.size() + headerOffset)) {
|
||||||
T item = section.get(position - subPosition - headerOffset);
|
T item = section.get(position - subPosition - headerOffset);
|
||||||
onBindViewHolder(holder, item, getItemViewType(item));
|
onBindViewHolder(holder, item, getItemViewType(item));
|
||||||
|
|
||||||
@ -209,7 +179,7 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size();
|
subPosition += section.size();
|
||||||
if(validHeader) {
|
if (validHeader) {
|
||||||
subPosition += 1;
|
subPosition += 1;
|
||||||
}
|
}
|
||||||
subHeader++;
|
subHeader++;
|
||||||
@ -217,13 +187,13 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void postBindView(UpdateView updateView, T item) {
|
private void postBindView(UpdateView updateView, T item) {
|
||||||
if(updateView.isCheckable()) {
|
if (updateView.isCheckable()) {
|
||||||
setChecked(updateView, selected.contains(item));
|
setChecked(updateView, selected.contains(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
View moreButton = updateView.findViewById(R.id.item_more);
|
View moreButton = updateView.findViewById(R.id.item_more);
|
||||||
if(moreButton != null) {
|
if (moreButton != null) {
|
||||||
if(onItemClickedListener != null) {
|
if (onItemClickedListener != null) {
|
||||||
PopupMenu popup = new PopupMenu(context, moreButton);
|
PopupMenu popup = new PopupMenu(context, moreButton);
|
||||||
Menu menu = popup.getMenu();
|
Menu menu = popup.getMenu();
|
||||||
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
||||||
@ -240,17 +210,17 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if (sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).size();
|
return sections.get(0).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(String header: headers) {
|
for (String header : headers) {
|
||||||
if(header != null) {
|
if (header != null) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
count += section.size();
|
count += section.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,25 +229,25 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if (sections.size() == 1 && !singleSectionHeader) {
|
||||||
return getItemViewType(sections.get(0).get(position));
|
return getItemViewType(sections.get(0).get(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
int subHeader = 0;
|
int subHeader = 0;
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
boolean validHeader = headers.get(subHeader) != null;
|
boolean validHeader = headers.get(subHeader) != null;
|
||||||
if(position == subPosition && validHeader) {
|
if (position == subPosition && validHeader) {
|
||||||
return VIEW_TYPE_HEADER;
|
return VIEW_TYPE_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
int headerOffset = validHeader ? 1 : 0;
|
int headerOffset = validHeader ? 1 : 0;
|
||||||
if(position < (subPosition + section.size() + headerOffset)) {
|
if (position < (subPosition + section.size() + headerOffset)) {
|
||||||
return getItemViewType(section.get(position - subPosition - headerOffset));
|
return getItemViewType(section.get(position - subPosition - headerOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size();
|
subPosition += section.size();
|
||||||
if(validHeader) {
|
if (validHeader) {
|
||||||
subPosition += 1;
|
subPosition += 1;
|
||||||
}
|
}
|
||||||
subHeader++;
|
subHeader++;
|
||||||
@ -286,28 +256,29 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateViewHolder(new BasicHeaderView(context));
|
return new UpdateViewHolder(new BasicHeaderView(context));
|
||||||
}
|
}
|
||||||
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
|
||||||
|
void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(view != null) {
|
if (view != null) {
|
||||||
view.setObject(header);
|
view.setObject(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public T getItemForPosition(int position) {
|
T getItemForPosition(int position) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if (sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).get(position);
|
return sections.get(0).get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
if(position == subPosition) {
|
if (position == subPosition) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(position <= (subPosition + section.size())) {
|
if (position <= (subPosition + section.size())) {
|
||||||
return section.get(position - subPosition - 1);
|
return section.get(position - subPosition - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,17 +287,18 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemPosition(T item) {
|
public int getItemPosition(T item) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if (sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).indexOf(item);
|
return sections.get(0).indexOf(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
subPosition += section.size() + 1;
|
subPosition += section.size() + 1;
|
||||||
|
|
||||||
int position = section.indexOf(item);
|
int position = section.indexOf(item);
|
||||||
if(position != -1) {
|
if (position != -1) {
|
||||||
return position + subPosition;
|
return position + subPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,6 +313,7 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
public void addSelected(T item) {
|
public void addSelected(T item) {
|
||||||
selected.add(item);
|
selected.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> getSelected() {
|
public List<T> getSelected() {
|
||||||
List<T> selected = new ArrayList<>();
|
List<T> selected = new ArrayList<>();
|
||||||
selected.addAll(this.selected);
|
selected.addAll(this.selected);
|
||||||
@ -348,17 +321,9 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clearSelected() {
|
public void clearSelected() {
|
||||||
// TODO: This needs to work with multiple sections
|
|
||||||
for(T item: selected) {
|
|
||||||
int index = sections.get(0).indexOf(item);
|
|
||||||
|
|
||||||
if(singleSectionHeader) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selected.clear();
|
selected.clear();
|
||||||
|
|
||||||
for(UpdateView updateView: selectedViews) {
|
for (UpdateView updateView : selectedViews) {
|
||||||
updateView.setChecked(false);
|
updateView.setChecked(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,9 +331,9 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
public void moveItem(int from, int to) {
|
public void moveItem(int from, int to) {
|
||||||
List<T> section = sections.get(0);
|
List<T> section = sections.get(0);
|
||||||
int max = section.size();
|
int max = section.size();
|
||||||
if(to >= max) {
|
if (to >= max) {
|
||||||
to = max - 1;
|
to = max - 1;
|
||||||
} else if(to < 0) {
|
} else if (to < 0) {
|
||||||
to = 0;
|
to = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,10 +342,11 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
notifyItemMoved(from, to);
|
notifyItemMoved(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeItem(T item) {
|
public void removeItem(T item) {
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for (List<T> section : sections) {
|
||||||
if(sections.size() > 1 || singleSectionHeader) {
|
if (sections.size() > 1 || singleSectionHeader) {
|
||||||
subPosition++;
|
subPosition++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,16 +361,18 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType);
|
protected abstract UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType);
|
||||||
public abstract void onBindViewHolder(UpdateViewHolder holder, T item, int viewType);
|
|
||||||
public abstract int getItemViewType(T item);
|
protected abstract void onBindViewHolder(UpdateViewHolder holder, T item, int viewType);
|
||||||
public void setCheckable(boolean checkable) {
|
|
||||||
this.checkable = checkable;
|
protected abstract int getItemViewType(T item);
|
||||||
}
|
|
||||||
public void setChecked(UpdateView updateView, boolean checked) {
|
private void setChecked(UpdateView updateView, boolean checked) {
|
||||||
updateView.setChecked(checked);
|
updateView.setChecked(checked);
|
||||||
}
|
}
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {}
|
|
||||||
|
void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
|
}
|
||||||
|
|
||||||
private void startActionMode(final UpdateView.UpdateViewHolder<T> holder) {
|
private void startActionMode(final UpdateView.UpdateViewHolder<T> holder) {
|
||||||
final UpdateView<T> updateView = holder.getUpdateView();
|
final UpdateView<T> updateView = holder.getUpdateView();
|
||||||
@ -470,21 +438,23 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopActionMode() {
|
public void stopActionMode() {
|
||||||
if(currentActionMode != null) {
|
if (currentActionMode != null) {
|
||||||
currentActionMode.finish();
|
currentActionMode.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNameIndex(String name) {
|
String getNameIndex(String name) {
|
||||||
return getNameIndex(name, false);
|
return getNameIndex(name, false);
|
||||||
}
|
}
|
||||||
public String getNameIndex(String name, boolean removeIgnoredArticles) {
|
|
||||||
if(name == null) {
|
String getNameIndex(String name, boolean removeIgnoredArticles) {
|
||||||
|
if (name == null) {
|
||||||
return "*";
|
return "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(removeIgnoredArticles) {
|
if (removeIgnoredArticles) {
|
||||||
if (ignoredArticles == null) {
|
if (ignoredArticles == null) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String ignoredArticlesString = prefs.getString(Constants.CACHE_KEY_IGNORE, "The El La Los Las Le Les");
|
String ignoredArticlesString = prefs.getString(Constants.CACHE_KEY_IGNORE, "The El La Los Las Le Les");
|
||||||
@ -510,7 +480,9 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
|
|||||||
|
|
||||||
public interface OnItemClickedListener<T> {
|
public interface OnItemClickedListener<T> {
|
||||||
void onItemClicked(UpdateView<T> updateView, T item);
|
void onItemClicked(UpdateView<T> updateView, T item);
|
||||||
|
|
||||||
void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<T> updateView, T item);
|
void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<T> updateView, T item);
|
||||||
|
|
||||||
boolean onContextItemSelected(MenuItem menuItem, UpdateView<T> updateView, T item);
|
boolean onContextItemSelected(MenuItem menuItem, UpdateView<T> updateView, T item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Subsonic.
|
|
||||||
Subsonic 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.
|
|
||||||
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
Copyright 2014 (C) Scott Jackson
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.User;
|
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
|
||||||
import net.nullsum.audinaut.util.UserUtil;
|
|
||||||
import net.nullsum.audinaut.view.BasicHeaderView;
|
|
||||||
import net.nullsum.audinaut.view.RecyclingImageView;
|
|
||||||
import net.nullsum.audinaut.view.SettingView;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.User.Setting;
|
|
||||||
|
|
||||||
public class SettingsAdapter extends SectionAdapter<Setting> {
|
|
||||||
private static final String TAG = SettingsAdapter.class.getSimpleName();
|
|
||||||
public final int VIEW_TYPE_SETTING = 1;
|
|
||||||
public final int VIEW_TYPE_SETTING_HEADER = 2;
|
|
||||||
|
|
||||||
private final User user;
|
|
||||||
private final boolean editable;
|
|
||||||
private final ImageLoader imageLoader;
|
|
||||||
|
|
||||||
public SettingsAdapter(Context context, User user, List<String> headers, List<List<User.Setting>> settingSections, ImageLoader imageLoader, boolean editable, OnItemClickedListener<Setting> onItemClickedListener) {
|
|
||||||
super(context, headers, settingSections, imageLoader != null);
|
|
||||||
this.user = user;
|
|
||||||
this.imageLoader = imageLoader;
|
|
||||||
this.editable = editable;
|
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
|
||||||
|
|
||||||
for(List<Setting> settings: sections) {
|
|
||||||
for (Setting setting : settings) {
|
|
||||||
if (setting.getValue()) {
|
|
||||||
addSelected(setting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position) {
|
|
||||||
int viewType = super.getItemViewType(position);
|
|
||||||
if(viewType == SectionAdapter.VIEW_TYPE_HEADER) {
|
|
||||||
if(position == 0 && imageLoader != null) {
|
|
||||||
return VIEW_TYPE_HEADER;
|
|
||||||
} else {
|
|
||||||
return VIEW_TYPE_SETTING_HEADER;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return viewType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description, int sectionIndex) {
|
|
||||||
View header = holder.getView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
|
||||||
if(viewType == VIEW_TYPE_SETTING_HEADER) {
|
|
||||||
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context));
|
|
||||||
} else {
|
|
||||||
return new UpdateView.UpdateViewHolder(new SettingView(context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) {
|
|
||||||
holder.getUpdateView().setObject(item, editable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(Setting item) {
|
|
||||||
return VIEW_TYPE_SETTING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChecked(UpdateView updateView, boolean checked) {
|
|
||||||
if(updateView instanceof SettingView) {
|
|
||||||
updateView.setChecked(checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, OnItemClickedListener<Setting> onItemClickedListener) {
|
|
||||||
return getSettingsAdapter(context, user, imageLoader, true, onItemClickedListener);
|
|
||||||
}
|
|
||||||
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean isEditable, OnItemClickedListener<Setting> onItemClickedListener) {
|
|
||||||
List<String> headers = new ArrayList<>();
|
|
||||||
List<List<User.Setting>> settingsSections = new ArrayList<>();
|
|
||||||
settingsSections.add(user.getSettings());
|
|
||||||
|
|
||||||
if(user.getMusicFolderSettings() != null) {
|
|
||||||
settingsSections.add(user.getMusicFolderSettings());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SettingsAdapter(context, user, headers, settingsSections, imageLoader, isEditable, onItemClickedListener);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,14 +19,8 @@
|
|||||||
package net.nullsum.audinaut.audiofx;
|
package net.nullsum.audinaut.audiofx;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.media.audiofx.AudioEffect;
|
|
||||||
import android.media.audiofx.LoudnessEnhancer;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class AudioEffectsController {
|
public class AudioEffectsController {
|
||||||
private static final String TAG = AudioEffectsController.class.getSimpleName();
|
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private int audioSessionId = 0;
|
private int audioSessionId = 0;
|
||||||
@ -39,7 +33,7 @@ public class AudioEffectsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
if(equalizerController != null) {
|
if (equalizerController != null) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.audiofx;
|
package net.nullsum.audinaut.audiofx;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.audiofx.BassBoost;
|
import android.media.audiofx.BassBoost;
|
||||||
import android.media.audiofx.Equalizer;
|
import android.media.audiofx.Equalizer;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backward-compatible wrapper for {@link Equalizer}, which is API Level 9.
|
* Backward-compatible wrapper for {@link Equalizer}, which is API Level 9.
|
||||||
*
|
*
|
||||||
@ -54,7 +55,7 @@ public class EqualizerController {
|
|||||||
equalizer = new Equalizer(0, audioSessionId);
|
equalizer = new Equalizer(0, audioSessionId);
|
||||||
bass = new BassBoost(0, audioSessionId);
|
bass = new BassBoost(0, audioSessionId);
|
||||||
loudnessAvailable = true;
|
loudnessAvailable = true;
|
||||||
loudnessEnhancerController = new LoudnessEnhancerController(context, audioSessionId);
|
loudnessEnhancerController = new LoudnessEnhancerController(audioSessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveSettings() {
|
public void saveSettings() {
|
||||||
@ -80,14 +81,14 @@ public class EqualizerController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAvailable() {
|
private boolean isAvailable() {
|
||||||
return equalizer != null && bass != null;
|
return equalizer != null && bass != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
try {
|
try {
|
||||||
return isAvailable() && equalizer.getEnabled();
|
return isAvailable() && equalizer.getEnabled();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,14 +98,14 @@ public class EqualizerController {
|
|||||||
released = true;
|
released = true;
|
||||||
equalizer.release();
|
equalizer.release();
|
||||||
bass.release();
|
bass.release();
|
||||||
if(loudnessEnhancerController != null && loudnessEnhancerController.isAvailable()) {
|
if (loudnessEnhancerController != null && loudnessEnhancerController.isAvailable()) {
|
||||||
loudnessEnhancerController.release();
|
loudnessEnhancerController.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Equalizer getEqualizer() {
|
public Equalizer getEqualizer() {
|
||||||
if(released) {
|
if (released) {
|
||||||
released = false;
|
released = false;
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
@ -116,8 +117,9 @@ public class EqualizerController {
|
|||||||
}
|
}
|
||||||
return equalizer;
|
return equalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BassBoost getBassBoost() {
|
public BassBoost getBassBoost() {
|
||||||
if(released) {
|
if (released) {
|
||||||
released = false;
|
released = false;
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
@ -128,8 +130,9 @@ public class EqualizerController {
|
|||||||
}
|
}
|
||||||
return bass;
|
return bass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoudnessEnhancerController getLoudnessEnhancerController() {
|
public LoudnessEnhancerController getLoudnessEnhancerController() {
|
||||||
if(loudnessAvailable && released) {
|
if (loudnessAvailable && released) {
|
||||||
released = false;
|
released = false;
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
@ -144,7 +147,6 @@ public class EqualizerController {
|
|||||||
private static class EqualizerSettings implements Serializable {
|
private static class EqualizerSettings implements Serializable {
|
||||||
|
|
||||||
private short[] bandLevels;
|
private short[] bandLevels;
|
||||||
private short preset;
|
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private short bass;
|
private short bass;
|
||||||
private int loudness;
|
private int loudness;
|
||||||
@ -152,26 +154,22 @@ public class EqualizerController {
|
|||||||
public EqualizerSettings() {
|
public EqualizerSettings() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EqualizerSettings(Equalizer equalizer, BassBoost boost, LoudnessEnhancerController loudnessEnhancerController) {
|
public EqualizerSettings(Equalizer equalizer, BassBoost boost, LoudnessEnhancerController loudnessEnhancerController) {
|
||||||
enabled = equalizer.getEnabled();
|
enabled = equalizer.getEnabled();
|
||||||
bandLevels = new short[equalizer.getNumberOfBands()];
|
bandLevels = new short[equalizer.getNumberOfBands()];
|
||||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
||||||
bandLevels[i] = equalizer.getBandLevel(i);
|
bandLevels[i] = equalizer.getBandLevel(i);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
preset = equalizer.getCurrentPreset();
|
|
||||||
} catch (Exception x) {
|
|
||||||
preset = -1;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
bass = boost.getRoundedStrength();
|
bass = boost.getRoundedStrength();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
bass = 0;
|
bass = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loudness = (int) loudnessEnhancerController.getGain();
|
loudness = (int) loudnessEnhancerController.getGain();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
loudness = 0;
|
loudness = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,11 +179,11 @@ public class EqualizerController {
|
|||||||
equalizer.setBandLevel(i, bandLevels[i]);
|
equalizer.setBandLevel(i, bandLevels[i]);
|
||||||
}
|
}
|
||||||
equalizer.setEnabled(enabled);
|
equalizer.setEnabled(enabled);
|
||||||
if(bass != 0) {
|
if (bass != 0) {
|
||||||
boost.setEnabled(true);
|
boost.setEnabled(true);
|
||||||
boost.setStrength(bass);
|
boost.setStrength(bass);
|
||||||
}
|
}
|
||||||
if(loudness != 0) {
|
if (loudness != 0) {
|
||||||
loudnessController.enable();
|
loudnessController.enable();
|
||||||
loudnessController.setGain(loudness);
|
loudnessController.setGain(loudness);
|
||||||
}
|
}
|
||||||
|
@ -18,22 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.audiofx;
|
package net.nullsum.audinaut.audiofx;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.media.audiofx.LoudnessEnhancer;
|
import android.media.audiofx.LoudnessEnhancer;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class LoudnessEnhancerController {
|
public class LoudnessEnhancerController {
|
||||||
private static final String TAG = LoudnessEnhancerController.class.getSimpleName();
|
private static final String TAG = LoudnessEnhancerController.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private LoudnessEnhancer enhancer;
|
private LoudnessEnhancer enhancer;
|
||||||
private boolean released = false;
|
|
||||||
private int audioSessionId = 0;
|
|
||||||
|
|
||||||
public LoudnessEnhancerController(Context context, int audioSessionId) {
|
public LoudnessEnhancerController(int audioSessionId) {
|
||||||
this.context = context;
|
|
||||||
try {
|
try {
|
||||||
this.audioSessionId = audioSessionId;
|
|
||||||
enhancer = new LoudnessEnhancer(audioSessionId);
|
enhancer = new LoudnessEnhancer(audioSessionId);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.w(TAG, "Failed to create enhancer", x);
|
Log.w(TAG, "Failed to create enhancer", x);
|
||||||
@ -47,7 +41,7 @@ public class LoudnessEnhancerController {
|
|||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
try {
|
try {
|
||||||
return isAvailable() && enhancer.getEnabled();
|
return isAvailable() && enhancer.getEnabled();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,6 +49,7 @@ public class LoudnessEnhancerController {
|
|||||||
public void enable() {
|
public void enable() {
|
||||||
enhancer.setEnabled(true);
|
enhancer.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable() {
|
public void disable() {
|
||||||
enhancer.setEnabled(false);
|
enhancer.setEnabled(false);
|
||||||
}
|
}
|
||||||
@ -62,6 +57,7 @@ public class LoudnessEnhancerController {
|
|||||||
public float getGain() {
|
public float getGain() {
|
||||||
return enhancer.getTargetGain();
|
return enhancer.getTargetGain();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGain(int gain) {
|
public void setGain(int gain) {
|
||||||
enhancer.setTargetGain(gain);
|
enhancer.setTargetGain(gain);
|
||||||
}
|
}
|
||||||
@ -69,7 +65,6 @@ public class LoudnessEnhancerController {
|
|||||||
public void release() {
|
public void release() {
|
||||||
if (isAvailable()) {
|
if (isAvailable()) {
|
||||||
enhancer.release();
|
enhancer.release();
|
||||||
released = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,26 +19,25 @@
|
|||||||
package net.nullsum.audinaut.domain;
|
package net.nullsum.audinaut.domain;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.text.Collator;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.UpdateHelper;
|
import net.nullsum.audinaut.util.UpdateHelper;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.text.Collator;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
@ -51,8 +50,9 @@ public class MusicDirectory implements Serializable {
|
|||||||
private List<Entry> children;
|
private List<Entry> children;
|
||||||
|
|
||||||
public MusicDirectory() {
|
public MusicDirectory() {
|
||||||
children = new ArrayList<Entry>();
|
children = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory(List<Entry> children) {
|
public MusicDirectory(List<Entry> children) {
|
||||||
this.children = children;
|
this.children = children;
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +82,11 @@ public class MusicDirectory implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addChild(Entry child) {
|
public void addChild(Entry child) {
|
||||||
if(child != null) {
|
if (child != null) {
|
||||||
children.add(child);
|
children.add(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChildren(List<Entry> children) {
|
public void addChildren(List<Entry> children) {
|
||||||
this.children.addAll(children);
|
this.children.addAll(children);
|
||||||
}
|
}
|
||||||
@ -103,7 +104,7 @@ public class MusicDirectory implements Serializable {
|
|||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entry> result = new ArrayList<Entry>(children.size());
|
List<Entry> result = new ArrayList<>(children.size());
|
||||||
for (Entry child : children) {
|
for (Entry child : children) {
|
||||||
if (child != null && child.isDirectory() && includeDirs || !child.isDirectory() && includeFiles) {
|
if (child != null && child.isDirectory() && includeDirs || !child.isDirectory() && includeFiles) {
|
||||||
result.add(child);
|
result.add(child);
|
||||||
@ -111,8 +112,9 @@ public class MusicDirectory implements Serializable {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized List<Entry> getSongs() {
|
public synchronized List<Entry> getSongs() {
|
||||||
List<Entry> result = new ArrayList<Entry>();
|
List<Entry> result = new ArrayList<>();
|
||||||
for (Entry child : children) {
|
for (Entry child : children) {
|
||||||
if (child != null && !child.isDirectory()) {
|
if (child != null && !child.isDirectory()) {
|
||||||
result.add(child);
|
result.add(child);
|
||||||
@ -125,24 +127,19 @@ public class MusicDirectory implements Serializable {
|
|||||||
return children.size();
|
return children.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shuffleChildren() {
|
public void sortChildren(Context context) {
|
||||||
Collections.shuffle(this.children);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sortChildren(Context context, int instance) {
|
|
||||||
sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sortChildren(boolean byYear) {
|
public void sortChildren(boolean byYear) {
|
||||||
EntryComparator.sort(children, byYear);
|
EntryComparator.sort(children, byYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean updateMetadata(MusicDirectory refreshedDirectory) {
|
public synchronized boolean updateMetadata(MusicDirectory refreshedDirectory) {
|
||||||
boolean metadataUpdated = false;
|
boolean metadataUpdated = false;
|
||||||
Iterator<Entry> it = children.iterator();
|
for (Entry entry : children) {
|
||||||
while(it.hasNext()) {
|
|
||||||
Entry entry = it.next();
|
|
||||||
int index = refreshedDirectory.children.indexOf(entry);
|
int index = refreshedDirectory.children.indexOf(entry);
|
||||||
if(index != -1) {
|
if (index != -1) {
|
||||||
final Entry refreshed = refreshedDirectory.children.get(index);
|
final Entry refreshed = refreshedDirectory.children.get(index);
|
||||||
|
|
||||||
entry.setTitle(refreshed.getTitle());
|
entry.setTitle(refreshed.getTitle());
|
||||||
@ -155,7 +152,7 @@ public class MusicDirectory implements Serializable {
|
|||||||
entry.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
entry.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
||||||
entry.setDiscNumber(refreshed.getDiscNumber());
|
entry.setDiscNumber(refreshed.getDiscNumber());
|
||||||
entry.setType(refreshed.getType());
|
entry.setType(refreshed.getType());
|
||||||
if(!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) {
|
if (!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) {
|
||||||
metadataUpdated = true;
|
metadataUpdated = true;
|
||||||
entry.setCoverArt(refreshed.getCoverArt());
|
entry.setCoverArt(refreshed.getCoverArt());
|
||||||
}
|
}
|
||||||
@ -173,7 +170,7 @@ public class MusicDirectory implements Serializable {
|
|||||||
found.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
found.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
||||||
found.setDiscNumber(refreshed.getDiscNumber());
|
found.setDiscNumber(refreshed.getDiscNumber());
|
||||||
found.setType(refreshed.getType());
|
found.setType(refreshed.getType());
|
||||||
if(!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) {
|
if (!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) {
|
||||||
found.setCoverArt(refreshed.getCoverArt());
|
found.setCoverArt(refreshed.getCoverArt());
|
||||||
metadataUpdate = DownloadService.METADATA_UPDATED_COVER_ART;
|
metadataUpdate = DownloadService.METADATA_UPDATED_COVER_ART;
|
||||||
}
|
}
|
||||||
@ -184,13 +181,14 @@ public class MusicDirectory implements Serializable {
|
|||||||
|
|
||||||
return metadataUpdated;
|
return metadataUpdated;
|
||||||
}
|
}
|
||||||
public synchronized boolean updateEntriesList(Context context, int instance, MusicDirectory refreshedDirectory) {
|
|
||||||
|
public synchronized boolean updateEntriesList(Context context, MusicDirectory refreshedDirectory) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
Iterator<Entry> it = children.iterator();
|
Iterator<Entry> it = children.iterator();
|
||||||
while(it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Entry entry = it.next();
|
Entry entry = it.next();
|
||||||
// No longer exists in here
|
// No longer exists in here
|
||||||
if(refreshedDirectory.children.indexOf(entry) == -1) {
|
if (refreshedDirectory.children.indexOf(entry) == -1) {
|
||||||
it.remove();
|
it.remove();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
@ -198,16 +196,16 @@ public class MusicDirectory implements Serializable {
|
|||||||
|
|
||||||
// Make sure we contain all children from refreshed set
|
// Make sure we contain all children from refreshed set
|
||||||
boolean resort = false;
|
boolean resort = false;
|
||||||
for(Entry refreshed: refreshedDirectory.children) {
|
for (Entry refreshed : refreshedDirectory.children) {
|
||||||
if(!this.children.contains(refreshed)) {
|
if (!this.children.contains(refreshed)) {
|
||||||
this.children.add(refreshed);
|
this.children.add(refreshed);
|
||||||
resort = true;
|
resort = true;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resort) {
|
if (resort) {
|
||||||
this.sortChildren(context, instance);
|
this.sortChildren(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
@ -218,7 +216,6 @@ public class MusicDirectory implements Serializable {
|
|||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String parent;
|
private String parent;
|
||||||
private String grandParent;
|
|
||||||
private String albumId;
|
private String albumId;
|
||||||
private String artistId;
|
private String artistId;
|
||||||
private boolean directory;
|
private boolean directory;
|
||||||
@ -233,26 +230,25 @@ public class MusicDirectory implements Serializable {
|
|||||||
private String transcodedContentType;
|
private String transcodedContentType;
|
||||||
private String transcodedSuffix;
|
private String transcodedSuffix;
|
||||||
private String coverArt;
|
private String coverArt;
|
||||||
private Long size;
|
|
||||||
private Integer duration;
|
private Integer duration;
|
||||||
private Integer bitRate;
|
private Integer bitRate;
|
||||||
private String path;
|
private String path;
|
||||||
private Integer discNumber;
|
private Integer discNumber;
|
||||||
private int type = 0;
|
private int type = 0;
|
||||||
private int closeness;
|
private int closeness;
|
||||||
private transient Artist linkedArtist;
|
|
||||||
|
|
||||||
public Entry() {
|
public Entry() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry(String id) {
|
public Entry(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry(Artist artist) {
|
public Entry(Artist artist) {
|
||||||
this.id = artist.getId();
|
this.id = artist.getId();
|
||||||
this.title = artist.getName();
|
this.title = artist.getName();
|
||||||
this.directory = true;
|
this.directory = true;
|
||||||
this.linkedArtist = artist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMetadata(File file) {
|
public void loadMetadata(File file) {
|
||||||
@ -260,16 +256,16 @@ public class MusicDirectory implements Serializable {
|
|||||||
MediaMetadataRetriever metadata = new MediaMetadataRetriever();
|
MediaMetadataRetriever metadata = new MediaMetadataRetriever();
|
||||||
metadata.setDataSource(file.getAbsolutePath());
|
metadata.setDataSource(file.getAbsolutePath());
|
||||||
String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER);
|
String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER);
|
||||||
if(discNumber == null) {
|
if (discNumber == null) {
|
||||||
discNumber = "1/1";
|
discNumber = "1/1";
|
||||||
}
|
}
|
||||||
int slashIndex = discNumber.indexOf("/");
|
int slashIndex = discNumber.indexOf("/");
|
||||||
if(slashIndex > 0) {
|
if (slashIndex > 0) {
|
||||||
discNumber = discNumber.substring(0, slashIndex);
|
discNumber = discNumber.substring(0, slashIndex);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
setDiscNumber(Integer.parseInt(discNumber));
|
setDiscNumber(Integer.parseInt(discNumber));
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Non numbers in disc field!");
|
Log.w(TAG, "Non numbers in disc field!");
|
||||||
}
|
}
|
||||||
String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
|
String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
|
||||||
@ -277,22 +273,23 @@ public class MusicDirectory implements Serializable {
|
|||||||
String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||||
setDuration(Integer.parseInt(length) / 1000);
|
setDuration(Integer.parseInt(length) / 1000);
|
||||||
String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
|
String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
|
||||||
if(artist != null) {
|
if (artist != null) {
|
||||||
setArtist(artist);
|
setArtist(artist);
|
||||||
}
|
}
|
||||||
String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
||||||
if(album != null) {
|
if (album != null) {
|
||||||
setAlbum(album);
|
setAlbum(album);
|
||||||
}
|
}
|
||||||
metadata.release();
|
metadata.release();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver", e);
|
Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rebaseTitleOffPath() {
|
public void rebaseTitleOffPath() {
|
||||||
try {
|
try {
|
||||||
String filename = getPath();
|
String filename = getPath();
|
||||||
if(filename == null) {
|
if (filename == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,13 +301,13 @@ public class MusicDirectory implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
index = filename.lastIndexOf('.');
|
index = filename.lastIndexOf('.');
|
||||||
if(index != -1) {
|
if (index != -1) {
|
||||||
filename = filename.substring(0, index);
|
filename = filename.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle(filename);
|
setTitle(filename);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to update title based off of path", e);
|
Log.w(TAG, "Failed to update title based off of path", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,14 +328,6 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getGrandParent() {
|
|
||||||
return grandParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGrandParent(String grandParent) {
|
|
||||||
this.grandParent = grandParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlbumId() {
|
public String getAlbumId() {
|
||||||
return albumId;
|
return albumId;
|
||||||
}
|
}
|
||||||
@ -379,18 +368,18 @@ public class MusicDirectory implements Serializable {
|
|||||||
return getParent() != null || getArtist() != null;
|
return getParent() != null || getArtist() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAlbum(String album) {
|
||||||
|
this.album = album;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAlbumDisplay() {
|
public String getAlbumDisplay() {
|
||||||
if(album != null && title.startsWith("Disc ")) {
|
if (album != null && title.startsWith("Disc ")) {
|
||||||
return album;
|
return album;
|
||||||
} else {
|
} else {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlbum(String album) {
|
|
||||||
this.album = album;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getArtist() {
|
public String getArtist() {
|
||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
@ -455,14 +444,6 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.transcodedSuffix = transcodedSuffix;
|
this.transcodedSuffix = transcodedSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSize(Long size) {
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getDuration() {
|
public Integer getDuration() {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
@ -506,9 +487,11 @@ public class MusicDirectory implements Serializable {
|
|||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(int type) {
|
public void setType(int type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSong() {
|
public boolean isSong() {
|
||||||
return type == TYPE_SONG;
|
return type == TYPE_SONG;
|
||||||
}
|
}
|
||||||
@ -521,18 +504,6 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.closeness = closeness;
|
this.closeness = closeness;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnlineId(Context context) {
|
|
||||||
try {
|
|
||||||
String cacheLocation = Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
|
||||||
return cacheLocation == null || id == null || id.indexOf(cacheLocation) == -1;
|
|
||||||
} catch(Exception e) {
|
|
||||||
Log.w(TAG, "Failed to check online id validity");
|
|
||||||
|
|
||||||
// Err on the side of default functionality
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@ -558,8 +529,8 @@ public class MusicDirectory implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class EntryComparator implements Comparator<Entry> {
|
public static class EntryComparator implements Comparator<Entry> {
|
||||||
private boolean byYear;
|
private final boolean byYear;
|
||||||
private Collator collator;
|
private final Collator collator;
|
||||||
|
|
||||||
public EntryComparator(boolean byYear) {
|
public EntryComparator(boolean byYear) {
|
||||||
this.byYear = byYear;
|
this.byYear = byYear;
|
||||||
@ -567,20 +538,28 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.collator.setStrength(Collator.PRIMARY);
|
this.collator.setStrength(Collator.PRIMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sort(List<Entry> entries, boolean byYear) {
|
||||||
|
try {
|
||||||
|
Collections.sort(entries, new EntryComparator(byYear));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Failed to sort MusicDirectory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
public int compare(Entry lhs, Entry rhs) {
|
||||||
if(lhs.isDirectory() && !rhs.isDirectory()) {
|
if (lhs.isDirectory() && !rhs.isDirectory()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(!lhs.isDirectory() && rhs.isDirectory()) {
|
} else if (!lhs.isDirectory() && rhs.isDirectory()) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if(lhs.isDirectory() && rhs.isDirectory()) {
|
} else if (lhs.isDirectory() && rhs.isDirectory()) {
|
||||||
if(byYear) {
|
if (byYear) {
|
||||||
Integer lhsYear = lhs.getYear();
|
Integer lhsYear = lhs.getYear();
|
||||||
Integer rhsYear = rhs.getYear();
|
Integer rhsYear = rhs.getYear();
|
||||||
if(lhsYear != null && rhsYear != null) {
|
if (lhsYear != null && rhsYear != null) {
|
||||||
return lhsYear.compareTo(rhsYear);
|
return lhsYear.compareTo(rhsYear);
|
||||||
} else if(lhsYear != null) {
|
} else if (lhsYear != null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rhsYear != null) {
|
} else if (rhsYear != null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -591,36 +570,25 @@ public class MusicDirectory implements Serializable {
|
|||||||
Integer lhsDisc = lhs.getDiscNumber();
|
Integer lhsDisc = lhs.getDiscNumber();
|
||||||
Integer rhsDisc = rhs.getDiscNumber();
|
Integer rhsDisc = rhs.getDiscNumber();
|
||||||
|
|
||||||
if(lhsDisc != null && rhsDisc != null) {
|
if (lhsDisc != null && rhsDisc != null) {
|
||||||
if(lhsDisc < rhsDisc) {
|
if (lhsDisc < rhsDisc) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(lhsDisc > rhsDisc) {
|
} else if (lhsDisc > rhsDisc) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer lhsTrack = lhs.getTrack();
|
Integer lhsTrack = lhs.getTrack();
|
||||||
Integer rhsTrack = rhs.getTrack();
|
Integer rhsTrack = rhs.getTrack();
|
||||||
if(lhsTrack != null && rhsTrack != null && lhsTrack != rhsTrack) {
|
if (lhsTrack != null && rhsTrack != null && !Objects.equals(lhsTrack, rhsTrack)) {
|
||||||
return lhsTrack.compareTo(rhsTrack);
|
return lhsTrack.compareTo(rhsTrack);
|
||||||
} else if(lhsTrack != null) {
|
} else if (lhsTrack != null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rhsTrack != null) {
|
} else if (rhsTrack != null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return collator.compare(lhs.getTitle(), rhs.getTitle());
|
return collator.compare(lhs.getTitle(), rhs.getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(List<Entry> entries) {
|
|
||||||
sort(entries, true);
|
|
||||||
}
|
|
||||||
public static void sort(List<Entry> entries, boolean byYear) {
|
|
||||||
try {
|
|
||||||
Collections.sort(entries, new EntryComparator(byYear));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.w(TAG, "Failed to sort MusicDirectory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,16 +35,24 @@ public class MusicFolder implements Serializable {
|
|||||||
private static final String TAG = MusicFolder.class.getSimpleName();
|
private static final String TAG = MusicFolder.class.getSimpleName();
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
public MusicFolder() {
|
public MusicFolder() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicFolder(String id, String name) {
|
public MusicFolder(String id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sort(List<MusicFolder> musicFolders) {
|
||||||
|
try {
|
||||||
|
Collections.sort(musicFolders, new MusicFolderComparator());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Failed to sort music folders", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -53,28 +61,13 @@ public class MusicFolder implements Serializable {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
public boolean getEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MusicFolderComparator implements Comparator<MusicFolder> {
|
public static class MusicFolderComparator implements Comparator<MusicFolder> {
|
||||||
public int compare(MusicFolder lhsMusicFolder, MusicFolder rhsMusicFolder) {
|
public int compare(MusicFolder lhsMusicFolder, MusicFolder rhsMusicFolder) {
|
||||||
if(lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) {
|
if (lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return lhsMusicFolder.getName().compareToIgnoreCase(rhsMusicFolder.getName());
|
return lhsMusicFolder.getName().compareToIgnoreCase(rhsMusicFolder.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(List<MusicFolder> musicFolders) {
|
|
||||||
try {
|
|
||||||
Collections.sort(musicFolders, new MusicFolderComparator());
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.w(TAG, "Failed to sort music folders", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,12 @@ package net.nullsum.audinaut.domain;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PlayerQueue implements Serializable {
|
public class PlayerQueue implements Serializable {
|
||||||
public List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
public final List<MusicDirectory.Entry> songs = new ArrayList<>();
|
||||||
public List<MusicDirectory.Entry> toDelete = new ArrayList<MusicDirectory.Entry>();
|
public final List<MusicDirectory.Entry> toDelete = new ArrayList<>();
|
||||||
public int currentPlayingIndex;
|
public int currentPlayingIndex;
|
||||||
public int currentPlayingPosition;
|
public int currentPlayingPosition;
|
||||||
public boolean renameCurrent = false;
|
public boolean renameCurrent = false;
|
||||||
public Date changed = null;
|
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,12 @@ public class Playlist implements Serializable {
|
|||||||
public Playlist() {
|
public Playlist() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Playlist(String id, String name) {
|
public Playlist(String id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Playlist(String id, String name, String owner, String comment, String songCount, String pub, String created, String changed, Integer duration) {
|
public Playlist(String id, String name, String owner, String comment, String songCount, String pub, String created, String changed, Integer duration) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -65,10 +67,6 @@ public class Playlist implements Serializable {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -81,10 +79,6 @@ public class Playlist implements Serializable {
|
|||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOwner(String owner) {
|
|
||||||
this.owner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getComment() {
|
public String getComment() {
|
||||||
return this.comment;
|
return this.comment;
|
||||||
}
|
}
|
||||||
@ -104,6 +98,7 @@ public class Playlist implements Serializable {
|
|||||||
public Boolean getPublic() {
|
public Boolean getPublic() {
|
||||||
return this.pub;
|
return this.pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPublic(Boolean pub) {
|
public void setPublic(Boolean pub) {
|
||||||
this.pub = pub;
|
this.pub = pub;
|
||||||
}
|
}
|
||||||
@ -112,7 +107,7 @@ public class Playlist implements Serializable {
|
|||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCreated(String created) {
|
private void setCreated(String created) {
|
||||||
if (created != null) {
|
if (created != null) {
|
||||||
try {
|
try {
|
||||||
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
||||||
@ -123,14 +118,12 @@ public class Playlist implements Serializable {
|
|||||||
this.created = null;
|
this.created = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void setCreated(Date created) {
|
|
||||||
this.created = created;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getChanged() {
|
public Date getChanged() {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
public void setChanged(String changed) {
|
|
||||||
|
private void setChanged(String changed) {
|
||||||
if (changed != null) {
|
if (changed != null) {
|
||||||
try {
|
try {
|
||||||
this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
|
this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
|
||||||
@ -141,16 +134,10 @@ public class Playlist implements Serializable {
|
|||||||
this.changed = null;
|
this.changed = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void setChanged(Date changed) {
|
|
||||||
this.changed = changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getDuration() {
|
public Integer getDuration() {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
public void setDuration(Integer duration) {
|
|
||||||
this.duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -159,13 +146,13 @@ public class Playlist implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if(o == this) {
|
if (o == this) {
|
||||||
return true;
|
return true;
|
||||||
} else if(o == null) {
|
} else if (o == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if(o instanceof String) {
|
} else if (o instanceof String) {
|
||||||
return o.equals(this.id);
|
return o.equals(this.id);
|
||||||
} else if(o.getClass() != getClass()) {
|
} else if (o.getClass() != getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,14 +161,14 @@ public class Playlist implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class PlaylistComparator implements Comparator<Playlist> {
|
public static class PlaylistComparator implements Comparator<Playlist> {
|
||||||
@Override
|
|
||||||
public int compare(Playlist playlist1, Playlist playlist2) {
|
|
||||||
return playlist1.getName().compareToIgnoreCase(playlist2.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Playlist> sort(List<Playlist> playlists) {
|
public static List<Playlist> sort(List<Playlist> playlists) {
|
||||||
Collections.sort(playlists, new PlaylistComparator());
|
Collections.sort(playlists, new PlaylistComparator());
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Playlist playlist1, Playlist playlist2) {
|
||||||
|
return playlist1.getName().compareToIgnoreCase(playlist2.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,24 +68,24 @@ public class SearchCritera {
|
|||||||
// * Replace spaces and wildcard '*' characters with ".*"
|
// * Replace spaces and wildcard '*' characters with ".*"
|
||||||
// * All other characters are properly quoted
|
// * All other characters are properly quoted
|
||||||
if (this.pattern == null) {
|
if (this.pattern == null) {
|
||||||
String regex = ".*";
|
StringBuilder regex = new StringBuilder(".*");
|
||||||
String currentPart = "";
|
StringBuilder currentPart = new StringBuilder();
|
||||||
for (int i = 0; i < query.length(); i++) {
|
for (int i = 0; i < query.length(); i++) {
|
||||||
char c = query.charAt(i);
|
char c = query.charAt(i);
|
||||||
if (c == '*' || c == ' ') {
|
if (c == '*' || c == ' ') {
|
||||||
regex += Pattern.quote(currentPart);
|
regex.append(Pattern.quote(currentPart.toString()));
|
||||||
regex += ".*";
|
regex.append(".*");
|
||||||
currentPart = "";
|
currentPart = new StringBuilder();
|
||||||
} else {
|
} else {
|
||||||
currentPart += c;
|
currentPart.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentPart.length() > 0) {
|
if (currentPart.length() > 0) {
|
||||||
regex += Pattern.quote(currentPart);
|
regex.append(Pattern.quote(currentPart.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
regex += ".*";
|
regex.append(".*");
|
||||||
this.pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
this.pattern = Pattern.compile(regex.toString(), Pattern.CASE_INSENSITIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
|
@ -50,13 +50,4 @@ public class SearchResult implements Serializable {
|
|||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArtists() {
|
|
||||||
return !artists.isEmpty();
|
|
||||||
}
|
|
||||||
public boolean hasAlbums() {
|
|
||||||
return !albums.isEmpty();
|
|
||||||
}
|
|
||||||
public boolean hasSongs() {
|
|
||||||
return !songs.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,21 +15,19 @@
|
|||||||
|
|
||||||
package net.nullsum.audinaut.domain;
|
package net.nullsum.audinaut.domain;
|
||||||
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class User implements Serializable {
|
public class User implements Serializable {
|
||||||
public static final String ADMIN = "adminRole";
|
|
||||||
public static final String SETTINGS = "settingsRole";
|
|
||||||
public static final String DOWNLOAD = "downloadRole";
|
|
||||||
public static final String UPLOAD = "uploadRole";
|
|
||||||
public static final String COVERART = "coverArtRole";
|
|
||||||
public static final String COMMENT = "commentRole";
|
|
||||||
public static final String STREAM = "streamRole";
|
|
||||||
public static final List<String> ROLES = new ArrayList<>();
|
public static final List<String> ROLES = new ArrayList<>();
|
||||||
|
private static final String ADMIN = "adminRole";
|
||||||
|
private static final String SETTINGS = "settingsRole";
|
||||||
|
private static final String DOWNLOAD = "downloadRole";
|
||||||
|
private static final String UPLOAD = "uploadRole";
|
||||||
|
private static final String COVERART = "coverArtRole";
|
||||||
|
private static final String COMMENT = "commentRole";
|
||||||
|
private static final String STREAM = "streamRole";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ROLES.add(ADMIN);
|
ROLES.add(ADMIN);
|
||||||
@ -41,66 +39,25 @@ public class User implements Serializable {
|
|||||||
ROLES.add(COMMENT);
|
ROLES.add(COMMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String username;
|
private final List<Setting> settings = new ArrayList<>();
|
||||||
private String password;
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
private List<Setting> settings = new ArrayList<Setting>();
|
|
||||||
private List<Setting> musicFolders;
|
private List<Setting> musicFolders;
|
||||||
|
|
||||||
public User() {
|
public User() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Setting> getSettings() {
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
public void setSettings(List<Setting> settings) {
|
|
||||||
this.settings.clear();
|
|
||||||
this.settings.addAll(settings);
|
|
||||||
}
|
|
||||||
public void addSetting(String name, Boolean value) {
|
public void addSetting(String name, Boolean value) {
|
||||||
settings.add(new Setting(name, value));
|
settings.add(new Setting(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMusicFolder(MusicFolder musicFolder) {
|
public void addMusicFolder(MusicFolder musicFolder) {
|
||||||
if(musicFolders == null) {
|
if (musicFolders == null) {
|
||||||
musicFolders = new ArrayList<>();
|
musicFolders = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName(), false));
|
musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName()));
|
||||||
}
|
}
|
||||||
public void addMusicFolder(MusicFolderSetting musicFolderSetting, boolean defaultValue) {
|
|
||||||
if(musicFolders == null) {
|
|
||||||
musicFolders = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
musicFolders.add(new MusicFolderSetting(musicFolderSetting.getName(), musicFolderSetting.getLabel(), defaultValue));
|
|
||||||
}
|
|
||||||
public List<Setting> getMusicFolderSettings() {
|
public List<Setting> getMusicFolderSettings() {
|
||||||
return musicFolders;
|
return musicFolders;
|
||||||
}
|
}
|
||||||
@ -112,6 +69,7 @@ public class User implements Serializable {
|
|||||||
public Setting() {
|
public Setting() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Setting(String name, Boolean value) {
|
public Setting(String name, Boolean value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@ -120,22 +78,21 @@ public class User implements Serializable {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getValue() {
|
public Boolean getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(Boolean value) {
|
public void setValue(Boolean value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MusicFolderSetting extends Setting {
|
public static class MusicFolderSetting extends Setting {
|
||||||
private String label;
|
private final String label;
|
||||||
|
|
||||||
public MusicFolderSetting() {
|
public MusicFolderSetting(String name, String label) {
|
||||||
|
super(name, false);
|
||||||
}
|
|
||||||
public MusicFolderSetting(String name, String label, Boolean value) {
|
|
||||||
super(name, value);
|
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
@ -26,13 +25,8 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
import net.nullsum.audinaut.adapter.DownloadFileAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
@ -42,9 +36,14 @@ import net.nullsum.audinaut.util.DownloadFileItemHelperCallback;
|
|||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.adapter.DownloadFileAdapter;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> implements SectionAdapter.OnItemClickedListener<DownloadFile> {
|
public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> implements SectionAdapter.OnItemClickedListener<DownloadFile> {
|
||||||
private long currentRevision;
|
private long currentRevision;
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
@ -69,17 +68,7 @@ public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> imple
|
|||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = () -> handler.post(this::update);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
handler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS);
|
executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS);
|
||||||
@ -104,11 +93,11 @@ public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> imple
|
|||||||
@Override
|
@Override
|
||||||
public List<DownloadFile> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<DownloadFile> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService == null) {
|
if (downloadService == null) {
|
||||||
return new ArrayList<DownloadFile>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DownloadFile> songList = new ArrayList<DownloadFile>();
|
List<DownloadFile> songList = new ArrayList<>();
|
||||||
songList.addAll(downloadService.getBackgroundDownloads());
|
songList.addAll(downloadService.getBackgroundDownloads());
|
||||||
currentRevision = downloadService.getDownloadListUpdateRevision();
|
currentRevision = downloadService.getDownloadListUpdateRevision();
|
||||||
return songList;
|
return songList;
|
||||||
@ -128,7 +117,7 @@ public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> imple
|
|||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
||||||
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, selectedItem);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, selectedItem);
|
||||||
if(!Util.isOffline(context)) {
|
if (!Util.isOffline(context)) {
|
||||||
menu.removeItem(R.id.song_menu_remove_playlist);
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,29 +132,24 @@ public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> imple
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||||
if(super.onOptionsItemSelected(menuItem)) {
|
if (super.onOptionsItemSelected(menuItem)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.menu_remove_all:
|
case R.id.menu_remove_all:
|
||||||
Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() {
|
Util.confirmDialog(context, R.string.download_menu_remove_all, "", (dialog, which) -> new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(context) {
|
getDownloadService().clearBackground();
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
getDownloadService().clearBackground();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
protected void done(Void result) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}.execute());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,14 +29,10 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.audiofx.EqualizerController;
|
import net.nullsum.audinaut.audiofx.EqualizerController;
|
||||||
import net.nullsum.audinaut.audiofx.LoudnessEnhancerController;
|
import net.nullsum.audinaut.audiofx.LoudnessEnhancerController;
|
||||||
@ -44,6 +40,9 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Scott on 10/27/13.
|
* Created by Scott on 10/27/13.
|
||||||
*/
|
*/
|
||||||
@ -52,7 +51,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
|
|
||||||
private static final int MENU_GROUP_PRESET = 100;
|
private static final int MENU_GROUP_PRESET = 100;
|
||||||
|
|
||||||
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
private final Map<Short, SeekBar> bars = new HashMap<>();
|
||||||
private SeekBar bassBar;
|
private SeekBar bassBar;
|
||||||
private SeekBar loudnessBar;
|
private SeekBar loudnessBar;
|
||||||
private EqualizerController equalizerController;
|
private EqualizerController equalizerController;
|
||||||
@ -73,7 +72,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
||||||
|
|
||||||
initEqualizer();
|
initEqualizer();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to initialize EQ", e);
|
Log.e(TAG, "Failed to initialize EQ", e);
|
||||||
Util.toast(context, "Failed to initialize EQ");
|
Util.toast(context, "Failed to initialize EQ");
|
||||||
context.onBackPressed();
|
context.onBackPressed();
|
||||||
@ -81,25 +80,17 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
|
|
||||||
final View presetButton = rootView.findViewById(R.id.equalizer_preset);
|
final View presetButton = rootView.findViewById(R.id.equalizer_preset);
|
||||||
registerForContextMenu(presetButton);
|
registerForContextMenu(presetButton);
|
||||||
presetButton.setOnClickListener(new View.OnClickListener() {
|
presetButton.setOnClickListener(view -> presetButton.showContextMenu());
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
presetButton.showContextMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
CheckBox enabledCheckBox = (CheckBox) rootView.findViewById(R.id.equalizer_enabled);
|
CheckBox enabledCheckBox = rootView.findViewById(R.id.equalizer_enabled);
|
||||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
enabledCheckBox.setOnCheckedChangeListener((compoundButton, b) -> {
|
||||||
@Override
|
try {
|
||||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
setEqualizerEnabled(b);
|
||||||
try {
|
} catch (Exception e) {
|
||||||
setEqualizerEnabled(b);
|
Log.e(TAG, "Failed to set EQ enabled", e);
|
||||||
} catch(Exception e) {
|
Util.toast(context, "Failed to set EQ enabled");
|
||||||
Log.e(TAG, "Failed to set EQ enabled", e);
|
context.onBackPressed();
|
||||||
Util.toast(context, "Failed to set EQ enabled");
|
|
||||||
context.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -119,7 +110,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
if (!equalizer.getEnabled()) {
|
if (!equalizer.getEnabled()) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to release controller", e);
|
Log.w(TAG, "Failed to release controller", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +126,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
super.onCreateContextMenu(menu, view, menuInfo);
|
super.onCreateContextMenu(menu, view, menuInfo);
|
||||||
if(!primaryFragment) {
|
if (!primaryFragment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +149,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||||
short preset = (short) menuItem.getItemId();
|
short preset = (short) menuItem.getItemId();
|
||||||
for(int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
equalizer.usePreset(preset);
|
equalizer.usePreset(preset);
|
||||||
i = 10;
|
i = 10;
|
||||||
@ -178,7 +169,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled);
|
editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
for(int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
equalizer.setEnabled(enabled);
|
equalizer.setEnabled(enabled);
|
||||||
updateBars(true);
|
updateBars(true);
|
||||||
@ -245,36 +236,36 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to update bars");
|
Log.e(TAG, "Failed to update bars");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initEqualizer() {
|
private void initEqualizer() {
|
||||||
LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.equalizer_layout);
|
LinearLayout layout = rootView.findViewById(R.id.equalizer_layout);
|
||||||
|
|
||||||
final short minEQLevel = equalizer.getBandLevelRange()[0];
|
final short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||||
final short maxEQLevel = equalizer.getBandLevelRange()[1];
|
final short maxEQLevel = equalizer.getBandLevelRange()[1];
|
||||||
|
|
||||||
// Setup Pregain
|
// Setup Pregain
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0);
|
masterLevel = (short) prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0);
|
||||||
initPregain(layout, minEQLevel, maxEQLevel);
|
initPregain(layout, minEQLevel, maxEQLevel);
|
||||||
|
|
||||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
||||||
final short band = i;
|
final short band = i;
|
||||||
|
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView levelTextView = bandBar.findViewById(R.id.equalizer_level);
|
||||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
SeekBar bar = bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||||
|
|
||||||
bars.put(band, bar);
|
bars.put(band, bar);
|
||||||
bar.setMax(maxEQLevel - minEQLevel);
|
bar.setMax(maxEQLevel - minEQLevel);
|
||||||
short level = equalizer.getBandLevel(band);
|
short level = equalizer.getBandLevel(band);
|
||||||
if(equalizer.getEnabled()) {
|
if (equalizer.getEnabled()) {
|
||||||
level = (short) (level - masterLevel);
|
level = (short) (level - masterLevel);
|
||||||
}
|
}
|
||||||
bar.setProgress(level - minEQLevel);
|
bar.setProgress(level - minEQLevel);
|
||||||
@ -290,7 +281,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
equalizer.setBandLevel(band, (short) (level + masterLevel));
|
equalizer.setBandLevel(band, (short) (level + masterLevel));
|
||||||
}
|
}
|
||||||
updateLevelText(levelTextView, level);
|
updateLevelText(levelTextView, level);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to change equalizer", e);
|
Log.e(TAG, "Failed to change equalizer", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,18 +297,18 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
layout.addView(bandBar);
|
layout.addView(bandBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearLayout specialLayout = (LinearLayout) rootView.findViewById(R.id.special_effects_layout);
|
LinearLayout specialLayout = rootView.findViewById(R.id.special_effects_layout);
|
||||||
|
|
||||||
// Setup bass booster
|
// Setup bass booster
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView bassTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView bassTextView = bandBar.findViewById(R.id.equalizer_level);
|
||||||
bassBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
bassBar = bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText(R.string.equalizer_bass_booster);
|
freqTextView.setText(R.string.equalizer_bass_booster);
|
||||||
bassBar.setEnabled(equalizer.getEnabled());
|
bassBar.setEnabled(equalizer.getEnabled());
|
||||||
short bassLevel = 0;
|
short bassLevel = 0;
|
||||||
if(bass.getEnabled()) {
|
if (bass.getEnabled()) {
|
||||||
bassLevel = bass.getRoundedStrength();
|
bassLevel = bass.getRoundedStrength();
|
||||||
}
|
}
|
||||||
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel));
|
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel));
|
||||||
@ -339,7 +330,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
bass.setEnabled(false);
|
bass.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error on changing bass: ", e);
|
Log.w(TAG, "Error on changing bass: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,17 +347,17 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
});
|
});
|
||||||
specialLayout.addView(bandBar);
|
specialLayout.addView(bandBar);
|
||||||
|
|
||||||
if(loudnessEnhancer != null && loudnessEnhancer.isAvailable()) {
|
if (loudnessEnhancer != null && loudnessEnhancer.isAvailable()) {
|
||||||
// Setup loudness enhancer
|
// Setup loudness enhancer
|
||||||
bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
freqTextView = bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView loudnessTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView loudnessTextView = bandBar.findViewById(R.id.equalizer_level);
|
||||||
loudnessBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
loudnessBar = bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText(R.string.equalizer_voice_booster);
|
freqTextView.setText(R.string.equalizer_voice_booster);
|
||||||
loudnessBar.setEnabled(equalizer.getEnabled());
|
loudnessBar.setEnabled(equalizer.getEnabled());
|
||||||
int loudnessLevel = 0;
|
int loudnessLevel = 0;
|
||||||
if(loudnessEnhancer.isEnabled()) {
|
if (loudnessEnhancer.isEnabled()) {
|
||||||
loudnessLevel = (int) loudnessEnhancer.getGain();
|
loudnessLevel = (int) loudnessEnhancer.getGain();
|
||||||
}
|
}
|
||||||
loudnessBar.setProgress(loudnessLevel / 100);
|
loudnessBar.setProgress(loudnessLevel / 100);
|
||||||
@ -377,18 +368,18 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
try {
|
try {
|
||||||
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress));
|
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress));
|
||||||
if(fromUser) {
|
if (fromUser) {
|
||||||
if(progress > 0) {
|
if (progress > 0) {
|
||||||
if(!loudnessEnhancer.isEnabled()) {
|
if (!loudnessEnhancer.isEnabled()) {
|
||||||
loudnessEnhancer.enable();
|
loudnessEnhancer.enable();
|
||||||
}
|
}
|
||||||
loudnessEnhancer.setGain(progress * 100);
|
loudnessEnhancer.setGain(progress * 100);
|
||||||
} else if(progress == 0 && loudnessEnhancer.isEnabled()) {
|
} else if (progress == 0 && loudnessEnhancer.isEnabled()) {
|
||||||
loudnessEnhancer.setGain(progress * 100);
|
loudnessEnhancer.setGain(progress * 100);
|
||||||
loudnessEnhancer.disable();
|
loudnessEnhancer.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error on changing loudness: ", e);
|
Log.w(TAG, "Error on changing loudness: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,13 +400,13 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
|
|
||||||
private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
|
private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView levelTextView = bandBar.findViewById(R.id.equalizer_level);
|
||||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
SeekBar bar = bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText("Master");
|
freqTextView.setText("Master");
|
||||||
|
|
||||||
bars.put((short)-1, bar);
|
bars.put((short) -1, bar);
|
||||||
bar.setMax(maxEQLevel - minEQLevel);
|
bar.setMax(maxEQLevel - minEQLevel);
|
||||||
bar.setProgress(masterLevel - minEQLevel);
|
bar.setProgress(masterLevel - minEQLevel);
|
||||||
bar.setEnabled(equalizer.getEnabled());
|
bar.setEnabled(equalizer.getEnabled());
|
||||||
@ -437,7 +428,7 @@ public class EqualizerFragment extends SubsonicFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateLevelText(levelTextView, masterLevel);
|
updateLevelText(levelTextView, masterLevel);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to change equalizer", e);
|
Log.e(TAG, "Failed to change equalizer", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.StatFs;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -17,32 +9,17 @@ import android.view.MenuItem;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.adapter.MainAdapter;
|
import net.nullsum.audinaut.adapter.MainAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
|
||||||
import net.nullsum.audinaut.util.EnvironmentVariables;
|
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
|
||||||
import net.nullsum.audinaut.util.LoadingTask;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import net.nullsum.audinaut.util.UserUtil;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MainFragment extends SelectRecyclerFragment<Integer> {
|
public class MainFragment extends SelectRecyclerFragment<Integer> {
|
||||||
private static final String TAG = MainFragment.class.getSimpleName();
|
|
||||||
public static final String SONGS_LIST_PREFIX = "songs-";
|
public static final String SONGS_LIST_PREFIX = "songs-";
|
||||||
public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest";
|
public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest";
|
||||||
public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed";
|
public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed";
|
||||||
@ -63,15 +40,6 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
onFinishSetupOptionsMenu(menu);
|
onFinishSetupOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if(super.onOptionsItemSelected(item)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return 0;
|
return 0;
|
||||||
@ -98,7 +66,7 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
return Arrays.asList(0);
|
return Collections.singletonList(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -107,15 +75,15 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showAlbumList(String type) {
|
private void showAlbumList(String type) {
|
||||||
if("genres".equals(type)) {
|
if ("genres".equals(type)) {
|
||||||
SubsonicFragment fragment = new SelectGenreFragment();
|
SubsonicFragment fragment = new SelectGenreFragment();
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
} else if("years".equals(type)) {
|
} else if ("years".equals(type)) {
|
||||||
SubsonicFragment fragment = new SelectYearFragment();
|
SubsonicFragment fragment = new SelectYearFragment();
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
} else {
|
} else {
|
||||||
// Clear out recently added count when viewing
|
// Clear out recently added count when viewing
|
||||||
if("newest".equals(type)) {
|
if ("newest".equals(type)) {
|
||||||
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
||||||
editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
|
editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
@ -132,59 +100,6 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showAboutDialog() {
|
|
||||||
new LoadingTask<Void>(context) {
|
|
||||||
Long[] used;
|
|
||||||
long bytesTotalFs;
|
|
||||||
long bytesAvailableFs;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
File rootFolder = FileUtil.getMusicDirectory(context);
|
|
||||||
StatFs stat = new StatFs(rootFolder.getPath());
|
|
||||||
bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
|
||||||
bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
|
||||||
|
|
||||||
used = FileUtil.getUsedSize(context, rootFolder);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
List<Integer> headers = new ArrayList<>();
|
|
||||||
List<String> details = new ArrayList<>();
|
|
||||||
|
|
||||||
headers.add(R.string.details_author);
|
|
||||||
details.add("Andrew Rabert");
|
|
||||||
|
|
||||||
headers.add(R.string.details_email);
|
|
||||||
details.add("ar@nullsum.net");
|
|
||||||
|
|
||||||
try {
|
|
||||||
headers.add(R.string.details_version);
|
|
||||||
details.add(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName);
|
|
||||||
} catch(Exception e) {
|
|
||||||
details.add("");
|
|
||||||
}
|
|
||||||
|
|
||||||
Resources res = context.getResources();
|
|
||||||
headers.add(R.string.details_files_cached);
|
|
||||||
details.add(Long.toString(used[0]));
|
|
||||||
|
|
||||||
headers.add(R.string.details_files_permanent);
|
|
||||||
details.add(Long.toString(used[1]));
|
|
||||||
|
|
||||||
headers.add(R.string.details_used_space);
|
|
||||||
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(used[2], context), Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context)));
|
|
||||||
|
|
||||||
headers.add(R.string.details_available_space);
|
|
||||||
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(bytesAvailableFs, context), Util.formatLocalizedBytes(bytesTotalFs, context)));
|
|
||||||
|
|
||||||
Util.showDetailsDialog(context, R.string.main_about_title, headers, details);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Integer> updateView, Integer item) {
|
public void onItemClicked(UpdateView<Integer> updateView, Integer item) {
|
||||||
if (item == R.string.main_albums_random) {
|
if (item == R.string.main_albums_random) {
|
||||||
@ -193,11 +108,11 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
showAlbumList("recent");
|
showAlbumList("recent");
|
||||||
} else if (item == R.string.main_albums_frequent) {
|
} else if (item == R.string.main_albums_frequent) {
|
||||||
showAlbumList("frequent");
|
showAlbumList("frequent");
|
||||||
} else if(item == R.string.main_albums_genres) {
|
} else if (item == R.string.main_albums_genres) {
|
||||||
showAlbumList("genres");
|
showAlbumList("genres");
|
||||||
} else if(item == R.string.main_albums_year) {
|
} else if (item == R.string.main_albums_year) {
|
||||||
showAlbumList("years");
|
showAlbumList("years");
|
||||||
} else if(item == R.string.main_albums_alphabetical) {
|
} else if (item == R.string.main_albums_alphabetical) {
|
||||||
showAlbumList("alphabeticalByName");
|
showAlbumList("alphabeticalByName");
|
||||||
} else if (item == R.string.main_songs_newest) {
|
} else if (item == R.string.main_songs_newest) {
|
||||||
showAlbumList(SONGS_NEWEST);
|
showAlbumList(SONGS_NEWEST);
|
||||||
@ -211,7 +126,8 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Integer> updateView, Integer item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Integer> updateView, Integer item) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Integer> updateView, Integer item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Integer> updateView, Integer item) {
|
||||||
|
@ -14,25 +14,13 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.GestureDetector.OnGestureListener;
|
import android.view.GestureDetector.OnGestureListener;
|
||||||
@ -42,19 +30,18 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.ViewFlipper;
|
import android.widget.ViewFlipper;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
||||||
|
import net.nullsum.audinaut.adapter.DownloadFileAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.audiofx.EqualizerController;
|
import net.nullsum.audinaut.audiofx.EqualizerController;
|
||||||
import net.nullsum.audinaut.domain.PlayerState;
|
import net.nullsum.audinaut.domain.PlayerState;
|
||||||
@ -62,26 +49,33 @@ import net.nullsum.audinaut.domain.RepeatMode;
|
|||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.service.DownloadService.OnSongChangedListener;
|
import net.nullsum.audinaut.service.DownloadService.OnSongChangedListener;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
||||||
import net.nullsum.audinaut.service.OfflineException;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
import net.nullsum.audinaut.util.DownloadFileItemHelperCallback;
|
||||||
|
import net.nullsum.audinaut.util.DrawableTint;
|
||||||
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
|
import net.nullsum.audinaut.util.MenuUtil;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.adapter.DownloadFileAdapter;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
import net.nullsum.audinaut.view.AutoRepeatButton;
|
||||||
import net.nullsum.audinaut.view.FadeOutAnimation;
|
import net.nullsum.audinaut.view.FadeOutAnimation;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
import static net.nullsum.audinaut.domain.PlayerState.*;
|
import static net.nullsum.audinaut.domain.PlayerState.COMPLETED;
|
||||||
import net.nullsum.audinaut.util.*;
|
import static net.nullsum.audinaut.domain.PlayerState.IDLE;
|
||||||
import net.nullsum.audinaut.view.AutoRepeatButton;
|
import static net.nullsum.audinaut.domain.PlayerState.PAUSED;
|
||||||
import java.util.ArrayList;
|
import static net.nullsum.audinaut.domain.PlayerState.STOPPED;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
|
|
||||||
public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener, SectionAdapter.OnItemClickedListener<DownloadFile>, OnSongChangedListener {
|
public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener, SectionAdapter.OnItemClickedListener<DownloadFile>, OnSongChangedListener {
|
||||||
private static final String TAG = NowPlayingFragment.class.getSimpleName();
|
|
||||||
private static final int PERCENTAGE_OF_SCREEN_FOR_SWIPE = 10;
|
private static final int PERCENTAGE_OF_SCREEN_FOR_SWIPE = 10;
|
||||||
|
|
||||||
private static final int ACTION_PREVIOUS = 1;
|
private static final int ACTION_PREVIOUS = 1;
|
||||||
@ -128,8 +122,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if(savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
if(savedInstanceState.getInt(Constants.FRAGMENT_DOWNLOAD_FLIPPER) == 1) {
|
if (savedInstanceState.getInt(Constants.FRAGMENT_DOWNLOAD_FLIPPER) == 1) {
|
||||||
startFlipped = true;
|
startFlipped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,198 +145,136 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
Display d = w.getDefaultDisplay();
|
Display d = w.getDefaultDisplay();
|
||||||
swipeDistance = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
|
swipeDistance = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
|
||||||
swipeVelocity = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
|
swipeVelocity = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
|
||||||
gestureScanner = new GestureDetector(this);
|
gestureScanner = new GestureDetector(context, this);
|
||||||
|
|
||||||
playlistFlipper = (ViewFlipper)rootView.findViewById(R.id.download_playlist_flipper);
|
playlistFlipper = rootView.findViewById(R.id.download_playlist_flipper);
|
||||||
emptyTextView = (TextView)rootView.findViewById(R.id.download_empty);
|
emptyTextView = rootView.findViewById(R.id.download_empty);
|
||||||
songTitleTextView = (TextView)rootView.findViewById(R.id.download_song_title);
|
songTitleTextView = rootView.findViewById(R.id.download_song_title);
|
||||||
albumArtImageView = (ImageView)rootView.findViewById(R.id.download_album_art_image);
|
albumArtImageView = rootView.findViewById(R.id.download_album_art_image);
|
||||||
positionTextView = (TextView)rootView.findViewById(R.id.download_position);
|
positionTextView = rootView.findViewById(R.id.download_position);
|
||||||
durationTextView = (TextView)rootView.findViewById(R.id.download_duration);
|
durationTextView = rootView.findViewById(R.id.download_duration);
|
||||||
statusTextView = (TextView)rootView.findViewById(R.id.download_status);
|
statusTextView = rootView.findViewById(R.id.download_status);
|
||||||
progressBar = (SeekBar)rootView.findViewById(R.id.download_progress_bar);
|
progressBar = rootView.findViewById(R.id.download_progress_bar);
|
||||||
previousButton = (AutoRepeatButton)rootView.findViewById(R.id.download_previous);
|
previousButton = rootView.findViewById(R.id.download_previous);
|
||||||
nextButton = (AutoRepeatButton)rootView.findViewById(R.id.download_next);
|
nextButton = rootView.findViewById(R.id.download_next);
|
||||||
rewindButton = (AutoRepeatButton) rootView.findViewById(R.id.download_rewind);
|
rewindButton = rootView.findViewById(R.id.download_rewind);
|
||||||
fastforwardButton = (AutoRepeatButton) rootView.findViewById(R.id.download_fastforward);
|
fastforwardButton = rootView.findViewById(R.id.download_fastforward);
|
||||||
pauseButton =rootView.findViewById(R.id.download_pause);
|
pauseButton = rootView.findViewById(R.id.download_pause);
|
||||||
stopButton =rootView.findViewById(R.id.download_stop);
|
stopButton = rootView.findViewById(R.id.download_stop);
|
||||||
startButton =rootView.findViewById(R.id.download_start);
|
startButton = rootView.findViewById(R.id.download_start);
|
||||||
repeatButton = (ImageButton)rootView.findViewById(R.id.download_repeat);
|
repeatButton = rootView.findViewById(R.id.download_repeat);
|
||||||
toggleListButton =rootView.findViewById(R.id.download_toggle_list);
|
toggleListButton = rootView.findViewById(R.id.download_toggle_list);
|
||||||
|
|
||||||
playlistView = (RecyclerView)rootView.findViewById(R.id.download_list);
|
playlistView = rootView.findViewById(R.id.download_list);
|
||||||
FastScroller fastScroller = (FastScroller) rootView.findViewById(R.id.download_fast_scroller);
|
FastScroller fastScroller = rootView.findViewById(R.id.download_fast_scroller);
|
||||||
fastScroller.attachRecyclerView(playlistView);
|
fastScroller.attachRecyclerView(playlistView);
|
||||||
setupLayoutManager(playlistView, false);
|
setupLayoutManager(playlistView, false);
|
||||||
ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, true));
|
ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, true));
|
||||||
touchHelper.attachToRecyclerView(playlistView);
|
touchHelper.attachToRecyclerView(playlistView);
|
||||||
|
|
||||||
View.OnTouchListener touchListener = new View.OnTouchListener() {
|
View.OnTouchListener touchListener = (v, me) -> gestureScanner.onTouchEvent(me);
|
||||||
@Override
|
|
||||||
public boolean onTouch(View v, MotionEvent me) {
|
|
||||||
return gestureScanner.onTouchEvent(me);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
pauseButton.setOnTouchListener(touchListener);
|
pauseButton.setOnTouchListener(touchListener);
|
||||||
stopButton.setOnTouchListener(touchListener);
|
stopButton.setOnTouchListener(touchListener);
|
||||||
startButton.setOnTouchListener(touchListener);
|
startButton.setOnTouchListener(touchListener);
|
||||||
emptyTextView.setOnTouchListener(touchListener);
|
emptyTextView.setOnTouchListener(touchListener);
|
||||||
albumArtImageView.setOnTouchListener(new View.OnTouchListener() {
|
albumArtImageView.setOnTouchListener((v, me) -> {
|
||||||
@Override
|
if (me.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
public boolean onTouch(View v, MotionEvent me) {
|
lastY = (int) me.getRawY();
|
||||||
if (me.getAction() == MotionEvent.ACTION_DOWN) {
|
}
|
||||||
lastY = (int) me.getRawY();
|
return gestureScanner.onTouchEvent(me);
|
||||||
|
});
|
||||||
|
|
||||||
|
previousButton.setOnClickListener(view -> {
|
||||||
|
warnIfStorageUnavailable();
|
||||||
|
new SilentBackgroundTask<Void>(context) {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Throwable {
|
||||||
|
getDownloadService().previous();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return gestureScanner.onTouchEvent(me);
|
}.execute();
|
||||||
}
|
setControlsVisible(true);
|
||||||
});
|
});
|
||||||
|
previousButton.setOnRepeatListener(() -> changeProgress(true));
|
||||||
|
|
||||||
previousButton.setOnClickListener(new View.OnClickListener() {
|
nextButton.setOnClickListener(view -> {
|
||||||
@Override
|
warnIfStorageUnavailable();
|
||||||
public void onClick(View view) {
|
new SilentBackgroundTask<Boolean>(context) {
|
||||||
warnIfStorageUnavailable();
|
@Override
|
||||||
new SilentBackgroundTask<Void>(context) {
|
protected Boolean doInBackground() throws Throwable {
|
||||||
@Override
|
getDownloadService().next();
|
||||||
protected Void doInBackground() throws Throwable {
|
return true;
|
||||||
getDownloadService().previous();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
setControlsVisible(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
previousButton.setOnRepeatListener(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
changeProgress(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nextButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
warnIfStorageUnavailable();
|
|
||||||
new SilentBackgroundTask<Boolean>(context) {
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground() throws Throwable {
|
|
||||||
getDownloadService().next();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
setControlsVisible(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
nextButton.setOnRepeatListener(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
changeProgress(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
rewindButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
changeProgress(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
rewindButton.setOnRepeatListener(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
changeProgress(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fastforwardButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
changeProgress(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fastforwardButton.setOnRepeatListener(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
changeProgress(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
pauseButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
getDownloadService().pause();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stopButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
getDownloadService().reset();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
startButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
warnIfStorageUnavailable();
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
start();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
repeatButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
RepeatMode repeatMode = getDownloadService().getRepeatMode().next();
|
|
||||||
getDownloadService().setRepeatMode(repeatMode);
|
|
||||||
switch (repeatMode) {
|
|
||||||
case OFF:
|
|
||||||
Util.toast(context, R.string.download_repeat_off);
|
|
||||||
break;
|
|
||||||
case ALL:
|
|
||||||
Util.toast(context, R.string.download_repeat_all);
|
|
||||||
break;
|
|
||||||
case SINGLE:
|
|
||||||
Util.toast(context, R.string.download_repeat_single);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
updateRepeatButton();
|
}.execute();
|
||||||
setControlsVisible(true);
|
setControlsVisible(true);
|
||||||
|
});
|
||||||
|
nextButton.setOnRepeatListener(() -> changeProgress(false));
|
||||||
|
|
||||||
|
rewindButton.setOnClickListener(view -> changeProgress(true));
|
||||||
|
rewindButton.setOnRepeatListener(() -> changeProgress(true));
|
||||||
|
|
||||||
|
fastforwardButton.setOnClickListener(view -> changeProgress(false));
|
||||||
|
fastforwardButton.setOnRepeatListener(() -> changeProgress(false));
|
||||||
|
|
||||||
|
|
||||||
|
pauseButton.setOnClickListener(view -> new SilentBackgroundTask<Void>(context) {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Throwable {
|
||||||
|
getDownloadService().pause();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}.execute());
|
||||||
|
|
||||||
|
stopButton.setOnClickListener(view -> new SilentBackgroundTask<Void>(context) {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Throwable {
|
||||||
|
getDownloadService().reset();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.execute());
|
||||||
|
|
||||||
|
startButton.setOnClickListener(view -> {
|
||||||
|
warnIfStorageUnavailable();
|
||||||
|
new SilentBackgroundTask<Void>(context) {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Throwable {
|
||||||
|
start();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
});
|
});
|
||||||
|
|
||||||
toggleListButton.setOnClickListener(new View.OnClickListener() {
|
repeatButton.setOnClickListener(view -> {
|
||||||
@Override
|
RepeatMode repeatMode = getDownloadService().getRepeatMode().next();
|
||||||
public void onClick(View view) {
|
getDownloadService().setRepeatMode(repeatMode);
|
||||||
toggleFullscreenAlbumArt();
|
switch (repeatMode) {
|
||||||
setControlsVisible(true);
|
case OFF:
|
||||||
|
Util.toast(context, R.string.download_repeat_off);
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
Util.toast(context, R.string.download_repeat_all);
|
||||||
|
break;
|
||||||
|
case SINGLE:
|
||||||
|
Util.toast(context, R.string.download_repeat_single);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
updateRepeatButton();
|
||||||
|
setControlsVisible(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
toggleListButton.setOnClickListener(view -> {
|
||||||
|
toggleFullscreenAlbumArt();
|
||||||
|
setControlsVisible(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
View overlay = rootView.findViewById(R.id.download_overlay_buttons);
|
View overlay = rootView.findViewById(R.id.download_overlay_buttons);
|
||||||
final int overlayHeight = overlay != null ? overlay.getHeight() : -1;
|
final int overlayHeight = overlay != null ? overlay.getHeight() : -1;
|
||||||
albumArtImageView.setOnClickListener(new View.OnClickListener() {
|
albumArtImageView.setOnClickListener(view -> {
|
||||||
@Override
|
if (overlayHeight == -1 || lastY < (view.getBottom() - overlayHeight)) {
|
||||||
public void onClick(View view) {
|
toggleFullscreenAlbumArt();
|
||||||
if (overlayHeight == -1 || lastY < (view.getBottom() - overlayHeight)) {
|
setControlsVisible(true);
|
||||||
toggleFullscreenAlbumArt();
|
|
||||||
setControlsVisible(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -383,20 +315,20 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.nowplaying_offline, menu);
|
menuInflater.inflate(R.menu.nowplaying_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.nowplaying, menu);
|
menuInflater.inflate(R.menu.nowplaying, menu);
|
||||||
}
|
}
|
||||||
if(downloadService != null && downloadService.isRemovePlayed()) {
|
if (downloadService != null && downloadService.isRemovePlayed()) {
|
||||||
menu.findItem(R.id.menu_remove_played).setChecked(true);
|
menu.findItem(R.id.menu_remove_played).setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(downloadService != null) {
|
if (downloadService != null) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
boolean equalizerOn = prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false);
|
boolean equalizerOn = prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false);
|
||||||
if (equalizerOn && downloadService != null) {
|
if (equalizerOn && downloadService != null) {
|
||||||
if(downloadService.getEqualizerController() != null && downloadService.getEqualizerController().isEnabled()) {
|
if (downloadService.getEqualizerController() != null && downloadService.getEqualizerController().isEnabled()) {
|
||||||
menu.findItem(R.id.menu_equalizer).setChecked(true);
|
menu.findItem(R.id.menu_equalizer).setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,23 +336,20 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
menu.removeItem(R.id.menu_equalizer);
|
menu.removeItem(R.id.menu_equalizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) {
|
if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) {
|
||||||
menu.findItem(R.id.menu_batch_mode).setChecked(true);
|
menu.findItem(R.id.menu_batch_mode).setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||||
if(menuItemSelected(menuItem.getItemId(), null)) {
|
return menuItemSelected(menuItem.getItemId(), null) || super.onOptionsItemSelected(menuItem);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(menuItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.nowplaying_context_offline, menu);
|
menuInflater.inflate(R.menu.nowplaying_context_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.nowplaying_context, menu);
|
menuInflater.inflate(R.menu.nowplaying_context, menu);
|
||||||
@ -436,39 +365,25 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
||||||
if(onContextItemSelected(menuItem, downloadFile.getSong())) {
|
return onContextItemSelected(menuItem, downloadFile.getSong()) || menuItemSelected(menuItem.getItemId(), downloadFile);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return menuItemSelected(menuItem.getItemId(), downloadFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean menuItemSelected(int menuItemId, final DownloadFile song) {
|
private boolean menuItemSelected(int menuItemId, final DownloadFile song) {
|
||||||
List<Entry> songs;
|
|
||||||
switch (menuItemId) {
|
switch (menuItemId) {
|
||||||
case R.id.menu_show_album: case R.id.menu_show_artist:
|
case R.id.menu_show_album:
|
||||||
|
case R.id.menu_show_artist:
|
||||||
Entry entry = song.getSong();
|
Entry entry = song.getSong();
|
||||||
|
|
||||||
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
||||||
String albumId;
|
String albumId;
|
||||||
String albumName;
|
String albumName;
|
||||||
if(menuItemId == R.id.menu_show_album) {
|
if (menuItemId == R.id.menu_show_album) {
|
||||||
if(Util.isTagBrowsing(context)) {
|
albumId = entry.getAlbumId();
|
||||||
albumId = entry.getAlbumId();
|
|
||||||
} else {
|
|
||||||
albumId = entry.getParent();
|
|
||||||
}
|
|
||||||
albumName = entry.getAlbum();
|
albumName = entry.getAlbum();
|
||||||
} else {
|
} else {
|
||||||
if(Util.isTagBrowsing(context)) {
|
albumId = entry.getArtistId();
|
||||||
albumId = entry.getArtistId();
|
|
||||||
} else {
|
|
||||||
albumId = entry.getGrandParent();
|
|
||||||
if(albumId == null) {
|
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getParent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
albumName = entry.getArtist();
|
albumName = entry.getArtist();
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
}
|
}
|
||||||
@ -476,23 +391,23 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, albumName);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, albumName);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Artist");
|
intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Artist");
|
||||||
|
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
try {
|
try {
|
||||||
// This should only be successful if this is a online song in offline mode
|
// This should only be successful if this is a online song in offline mode
|
||||||
Integer.parseInt(entry.getParent());
|
Integer.parseInt(entry.getParent());
|
||||||
String root = FileUtil.getMusicDirectory(context).getPath();
|
String root = FileUtil.getMusicDirectory(context).getPath();
|
||||||
String id = root + "/" + entry.getPath();
|
String id = root + "/" + entry.getPath();
|
||||||
id = id.substring(0, id.lastIndexOf("/"));
|
id = id.substring(0, id.lastIndexOf("/"));
|
||||||
if(menuItemId == R.id.menu_show_album) {
|
if (menuItemId == R.id.menu_show_album) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id);
|
||||||
}
|
}
|
||||||
id = id.substring(0, id.lastIndexOf("/"));
|
id = id.substring(0, id.lastIndexOf("/"));
|
||||||
if(menuItemId != R.id.menu_show_album) {
|
if (menuItemId != R.id.menu_show_album) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist());
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist());
|
||||||
intent.removeExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID);
|
intent.removeExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Do nothing, entry.getParent() is fine
|
// Do nothing, entry.getParent() is fine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,24 +416,19 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
Util.startActivityWithoutTransition(context, intent);
|
Util.startActivityWithoutTransition(context, intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_remove_all:
|
case R.id.menu_remove_all:
|
||||||
Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() {
|
Util.confirmDialog(context, R.string.download_menu_remove_all, "", (dialog, which) -> new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new SilentBackgroundTask<Void>(context) {
|
getDownloadService().setShufflePlayEnabled(false);
|
||||||
@Override
|
getDownloadService().clear();
|
||||||
protected Void doInBackground() throws Throwable {
|
return null;
|
||||||
getDownloadService().setShufflePlayEnabled(false);
|
|
||||||
getDownloadService().clear();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
context.closeNowPlaying();
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
protected void done(Void result) {
|
||||||
|
context.closeNowPlaying();
|
||||||
|
}
|
||||||
|
}.execute());
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_remove_played:
|
case R.id.menu_remove_played:
|
||||||
if (getDownloadService().isRemovePlayed()) {
|
if (getDownloadService().isRemovePlayed()) {
|
||||||
@ -543,7 +453,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
}.execute();
|
}.execute();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_save_playlist:
|
case R.id.menu_save_playlist:
|
||||||
List<Entry> entries = new LinkedList<Entry>();
|
List<Entry> entries = new LinkedList<>();
|
||||||
for (DownloadFile downloadFile : getDownloadService().getSongs()) {
|
for (DownloadFile downloadFile : getDownloadService().getSongs()) {
|
||||||
entries.add(downloadFile.getSong());
|
entries.add(downloadFile.getSong());
|
||||||
}
|
}
|
||||||
@ -556,7 +466,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if (downloadService != null) {
|
if (downloadService != null) {
|
||||||
EqualizerController controller = downloadService.getEqualizerController();
|
EqualizerController controller = downloadService.getEqualizerController();
|
||||||
if(controller != null) {
|
if (controller != null) {
|
||||||
SubsonicFragment fragment = new EqualizerFragment();
|
SubsonicFragment fragment = new EqualizerFragment();
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
setControlsVisible(true);
|
setControlsVisible(true);
|
||||||
@ -568,8 +478,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
// Any failed condition will get here
|
// Any failed condition will get here
|
||||||
Util.toast(context, "Failed to start equalizer. Try restarting.");
|
Util.toast(context, "Failed to start equalizer. Try restarting.");
|
||||||
return true;
|
return true;
|
||||||
}case R.id.menu_batch_mode:
|
}
|
||||||
if(Util.isBatchMode(context)) {
|
case R.id.menu_batch_mode:
|
||||||
|
if (Util.isBatchMode(context)) {
|
||||||
Util.setBatchMode(context, false);
|
Util.setBatchMode(context, false);
|
||||||
songListAdapter.notifyDataSetChanged();
|
songListAdapter.notifyDataSetChanged();
|
||||||
} else {
|
} else {
|
||||||
@ -587,12 +498,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
if(this.primaryFragment) {
|
if (this.primaryFragment) {
|
||||||
onResumeHandlers();
|
onResumeHandlers();
|
||||||
} else {
|
} else {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onResumeHandlers() {
|
private void onResumeHandlers() {
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
setControlsVisible(true);
|
setControlsVisible(true);
|
||||||
@ -603,22 +515,17 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
startFlipped = false;
|
startFlipped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateButtons();
|
if (currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) {
|
||||||
|
getImageLoader().loadImage(albumArtImageView, null, true, false);
|
||||||
if(currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) {
|
|
||||||
getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.runWhenServiceAvailable(new Runnable() {
|
context.runWhenServiceAvailable(() -> {
|
||||||
@Override
|
if (primaryFragment) {
|
||||||
public void run() {
|
DownloadService downloadService1 = getDownloadService();
|
||||||
if (primaryFragment) {
|
downloadService1.addOnSongChangedListener(NowPlayingFragment.this);
|
||||||
DownloadService downloadService = getDownloadService();
|
|
||||||
downloadService.addOnSongChangedListener(NowPlayingFragment.this, true);
|
|
||||||
}
|
|
||||||
updateRepeatButton();
|
|
||||||
updateTitle();
|
|
||||||
}
|
}
|
||||||
|
updateRepeatButton();
|
||||||
|
updateTitle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,8 +534,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
super.onPause();
|
super.onPause();
|
||||||
onPauseHandlers();
|
onPauseHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPauseHandlers() {
|
private void onPauseHandlers() {
|
||||||
if(executorService != null) {
|
if (executorService != null) {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if (downloadService != null) {
|
if (downloadService != null) {
|
||||||
downloadService.removeOnSongChangeListener(this);
|
downloadService.removeOnSongChangeListener(this);
|
||||||
@ -640,8 +548,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
@Override
|
@Override
|
||||||
public void setPrimaryFragment(boolean primary) {
|
public void setPrimaryFragment(boolean primary) {
|
||||||
super.setPrimaryFragment(primary);
|
super.setPrimaryFragment(primary);
|
||||||
if(rootView != null) {
|
if (rootView != null) {
|
||||||
if(primary) {
|
if (primary) {
|
||||||
onResumeHandlers();
|
onResumeHandlers();
|
||||||
} else {
|
} else {
|
||||||
onPauseHandlers();
|
onPauseHandlers();
|
||||||
@ -650,16 +558,17 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(int title) {
|
void setTitle(int title) {
|
||||||
this.title = context.getResources().getString(title);
|
this.title = context.getResources().getString(title);
|
||||||
if(this.primaryFragment) {
|
if (this.primaryFragment) {
|
||||||
context.setTitle(this.title);
|
context.setTitle(this.title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSubtitle(CharSequence title) {
|
void setSubtitle(CharSequence title) {
|
||||||
this.subtitle = title;
|
this.subtitle = title;
|
||||||
if(this.primaryFragment) {
|
if (this.primaryFragment) {
|
||||||
context.setSubtitle(title);
|
context.setSubtitle(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -675,22 +584,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = () -> handler.post(() -> setControlsVisible(false));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
handler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
setControlsVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
hideControlsFuture = executorService.schedule(runnable, 3000L, TimeUnit.MILLISECONDS);
|
hideControlsFuture = executorService.schedule(runnable, 3000L, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setControlsVisible(boolean visible) {
|
private void setControlsVisible(boolean visible) {
|
||||||
DownloadService downloadService = getDownloadService();
|
|
||||||
try {
|
try {
|
||||||
long duration = 1700L;
|
long duration = 1700L;
|
||||||
FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration);
|
FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration);
|
||||||
@ -698,17 +596,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
if (visible) {
|
if (visible) {
|
||||||
scheduleHideControls();
|
scheduleHideControls();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateButtons() {
|
|
||||||
if(context == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scroll to current playing/downloading.
|
// Scroll to current playing/downloading.
|
||||||
private void scrollToCurrent() {
|
private void scrollToCurrent() {
|
||||||
if (getDownloadService() == null || songListAdapter == null) {
|
if (getDownloadService() == null || songListAdapter == null) {
|
||||||
@ -718,13 +610,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
// Try to get position of current playing/downloading
|
// Try to get position of current playing/downloading
|
||||||
int position = songListAdapter.getItemPosition(currentPlaying);
|
int position = songListAdapter.getItemPosition(currentPlaying);
|
||||||
if(position == -1) {
|
if (position == -1) {
|
||||||
DownloadFile currentDownloading = getDownloadService().getCurrentDownloading();
|
DownloadFile currentDownloading = getDownloadService().getCurrentDownloading();
|
||||||
position = songListAdapter.getItemPosition(currentDownloading);
|
position = songListAdapter.getItemPosition(currentDownloading);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If found, scroll to it
|
// If found, scroll to it
|
||||||
if(position != -1) {
|
if (position != -1) {
|
||||||
// RecyclerView.scrollToPosition just puts it on the screen (ie: bottom if scrolled below it)
|
// RecyclerView.scrollToPosition just puts it on the screen (ie: bottom if scrolled below it)
|
||||||
LinearLayoutManager layoutManager = (LinearLayoutManager) playlistView.getLayoutManager();
|
LinearLayoutManager layoutManager = (LinearLayoutManager) playlistView.getLayoutManager();
|
||||||
layoutManager.scrollToPositionWithOffset(position, 0);
|
layoutManager.scrollToPositionWithOffset(position, 0);
|
||||||
@ -732,26 +624,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
if(startFlipped) {
|
if (startFlipped) {
|
||||||
startFlipped = false;
|
startFlipped = false;
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMinutes(int progress) {
|
|
||||||
if(progress < 30) {
|
|
||||||
return progress + 1;
|
|
||||||
} else if(progress < 49) {
|
|
||||||
return (progress - 30) * 5 + getMinutes(29);
|
|
||||||
} else if(progress < 57) {
|
|
||||||
return (progress - 48) * 30 + getMinutes(48);
|
|
||||||
} else if(progress < 81) {
|
|
||||||
return (progress - 56) * 60 + getMinutes(56);
|
|
||||||
} else {
|
|
||||||
return (progress - 80) * 150 + getMinutes(80);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleFullscreenAlbumArt() {
|
private void toggleFullscreenAlbumArt() {
|
||||||
if (playlistFlipper.getDisplayedChild() == 1) {
|
if (playlistFlipper.getDisplayedChild() == 1) {
|
||||||
playlistFlipper.setInAnimation(AnimationUtils.loadAnimation(context, R.anim.push_down_in));
|
playlistFlipper.setInAnimation(AnimationUtils.loadAnimation(context, R.anim.push_down_in));
|
||||||
@ -786,7 +664,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
private void changeProgress(final boolean rewind) {
|
private void changeProgress(final boolean rewind) {
|
||||||
final DownloadService downloadService = getDownloadService();
|
final DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService == null) {
|
if (downloadService == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,7 +673,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
if(rewind) {
|
if (rewind) {
|
||||||
seekTo = downloadService.rewind();
|
seekTo = downloadService.rewind();
|
||||||
} else {
|
} else {
|
||||||
seekTo = downloadService.fastForward();
|
seekTo = downloadService.fastForward();
|
||||||
@ -841,13 +719,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
action = ACTION_REWIND;
|
action = ACTION_REWIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(action > 0) {
|
if (action > 0) {
|
||||||
final int performAction = action;
|
final int performAction = action;
|
||||||
warnIfStorageUnavailable();
|
warnIfStorageUnavailable();
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
switch(performAction) {
|
switch (performAction) {
|
||||||
case ACTION_NEXT:
|
case ACTION_NEXT:
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
break;
|
break;
|
||||||
@ -929,14 +807,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
getImageLoader().loadImage(albumArtImageView, song, true, true);
|
getImageLoader().loadImage(albumArtImageView, song, true, true);
|
||||||
|
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService.isShufflePlayEnabled()) {
|
if (downloadService.isShufflePlayEnabled()) {
|
||||||
setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_shuffle));
|
setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_shuffle));
|
||||||
} else {
|
} else {
|
||||||
setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
|
setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
songTitleTextView.setText(null);
|
songTitleTextView.setText(null);
|
||||||
getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false);
|
getImageLoader().loadImage(albumArtImageView, null, true, false);
|
||||||
setSubtitle(null);
|
setSubtitle(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -946,14 +824,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
currentPlayingSize = songs.size();
|
currentPlayingSize = songs.size();
|
||||||
|
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService.isShufflePlayEnabled()) {
|
if (downloadService.isShufflePlayEnabled()) {
|
||||||
emptyTextView.setText(R.string.download_shuffle_loading);
|
emptyTextView.setText(R.string.download_shuffle_loading);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
emptyTextView.setText(R.string.download_empty);
|
emptyTextView.setText(R.string.download_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(songListAdapter == null) {
|
if (songListAdapter == null) {
|
||||||
songList = new ArrayList<>();
|
songList = new ArrayList<>();
|
||||||
songList.addAll(songs);
|
songList.addAll(songs);
|
||||||
playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList, NowPlayingFragment.this));
|
playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList, NowPlayingFragment.this));
|
||||||
@ -965,12 +842,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
emptyTextView.setVisibility(songs.isEmpty() ? View.VISIBLE : View.GONE);
|
emptyTextView.setVisibility(songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if(scrollWhenLoaded) {
|
if (scrollWhenLoaded) {
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
scrollWhenLoaded = false;
|
scrollWhenLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.currentPlaying != currentPlaying) {
|
if (this.currentPlaying != currentPlaying) {
|
||||||
onSongChanged(currentPlaying, currentPlayingIndex);
|
onSongChanged(currentPlaying, currentPlayingIndex);
|
||||||
onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL);
|
onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL);
|
||||||
} else {
|
} else {
|
||||||
@ -987,13 +864,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
int millisTotal = duration == null ? 0 : duration;
|
int millisTotal = duration == null ? 0 : duration;
|
||||||
|
|
||||||
positionTextView.setText(Util.formatDuration(millisPlayed / 1000));
|
positionTextView.setText(Util.formatDuration(millisPlayed / 1000));
|
||||||
if(millisTotal > 0) {
|
if (millisTotal > 0) {
|
||||||
durationTextView.setText(Util.formatDuration(millisTotal / 1000));
|
durationTextView.setText(Util.formatDuration(millisTotal / 1000));
|
||||||
} else {
|
} else {
|
||||||
durationTextView.setText("-:--");
|
durationTextView.setText("-:--");
|
||||||
}
|
}
|
||||||
progressBar.setMax(millisTotal == 0 ? 100 : millisTotal); // Work-around for apparent bug.
|
progressBar.setMax(millisTotal == 0 ? 100 : millisTotal); // Work-around for apparent bug.
|
||||||
if(!seekInProgress) {
|
if (!seekInProgress) {
|
||||||
progressBar.setProgress(millisPlayed);
|
progressBar.setProgress(millisPlayed);
|
||||||
}
|
}
|
||||||
progressBar.setEnabled(isSeekable);
|
progressBar.setEnabled(isSeekable);
|
||||||
@ -1006,11 +883,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStateUpdate(DownloadFile downloadFile, PlayerState playerState) {
|
public void onStateUpdate(PlayerState playerState) {
|
||||||
switch (playerState) {
|
switch (playerState) {
|
||||||
case DOWNLOADING:
|
case DOWNLOADING:
|
||||||
if(currentPlaying != null) {
|
if (currentPlaying != null) {
|
||||||
if(Util.isWifiRequiredForDownload(context)) {
|
if (Util.isWifiRequiredForDownload(context)) {
|
||||||
statusTextView.setText(context.getResources().getString(R.string.download_playerstate_mobile_disabled));
|
statusTextView.setText(context.getResources().getString(R.string.download_playerstate_mobile_disabled));
|
||||||
} else {
|
} else {
|
||||||
long bytes = currentPlaying.getPartialFile().length();
|
long bytes = currentPlaying.getPartialFile().length();
|
||||||
@ -1022,9 +899,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
statusTextView.setText(R.string.download_playerstate_buffering);
|
statusTextView.setText(R.string.download_playerstate_buffering);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(currentPlaying != null) {
|
if (currentPlaying != null) {
|
||||||
Entry entry = currentPlaying.getSong();
|
Entry entry = currentPlaying.getSong();
|
||||||
if(entry.getAlbum() != null) {
|
if (entry.getAlbum() != null) {
|
||||||
String artist = "";
|
String artist = "";
|
||||||
if (entry.getArtist() != null) {
|
if (entry.getArtist() != null) {
|
||||||
artist = currentPlaying.getSong().getArtist().trim() + " - ";
|
artist = currentPlaying.getSong().getArtist().trim() + " - ";
|
||||||
@ -1061,12 +938,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMetadataUpdate(Entry song, int fieldChange) {
|
public void onMetadataUpdate(Entry song, int fieldChange) {
|
||||||
if(song != null && albumArtImageView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
|
if (song != null && albumArtImageView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
|
||||||
getImageLoader().loadImage(albumArtImageView, song, true, true);
|
getImageLoader().loadImage(albumArtImageView, song, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRepeatButton() {
|
private void updateRepeatButton() {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
switch (downloadService.getRepeatMode()) {
|
switch (downloadService.getRepeatMode()) {
|
||||||
case OFF:
|
case OFF:
|
||||||
@ -1082,9 +959,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void updateTitle() {
|
|
||||||
DownloadService downloadService = getDownloadService();
|
|
||||||
|
|
||||||
|
private void updateTitle() {
|
||||||
String title = context.getResources().getString(R.string.button_bar_now_playing);
|
String title = context.getResources().getString(R.string.button_bar_now_playing);
|
||||||
|
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
@ -1095,8 +971,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||||||
List<DownloadFile> selected = getCurrentAdapter().getSelected();
|
List<DownloadFile> selected = getCurrentAdapter().getSelected();
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
for(DownloadFile downloadFile: selected) {
|
for (DownloadFile downloadFile : selected) {
|
||||||
if(downloadFile.getSong() != null) {
|
if (downloadFile.getSong() != null) {
|
||||||
entries.add(downloadFile.getSong());
|
entries.add(downloadFile.getSong());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,32 +26,33 @@ import android.os.Bundle;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceFragment;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
||||||
private static final String TAG = PreferenceCompatFragment.class.getSimpleName();
|
|
||||||
private static final int FIRST_REQUEST_CODE = 100;
|
private static final int FIRST_REQUEST_CODE = 100;
|
||||||
private static final int MSG_BIND_PREFERENCES = 1;
|
private static final int MSG_BIND_PREFERENCES = 1;
|
||||||
private static final String PREFERENCES_TAG = "android:preferences";
|
private static final String PREFERENCES_TAG = "android:preferences";
|
||||||
private boolean mHavePrefs;
|
private boolean mHavePrefs;
|
||||||
private boolean mInitDone;
|
private boolean mInitDone;
|
||||||
private ListView mList;
|
private ListView mList;
|
||||||
|
final private Runnable mRequestFocus = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mList.focusableViewAvailable(mList);
|
||||||
|
}
|
||||||
|
};
|
||||||
private PreferenceManager mPreferenceManager;
|
private PreferenceManager mPreferenceManager;
|
||||||
|
private final Handler mHandler = new Handler() {
|
||||||
private Handler mHandler = new Handler() {
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
@ -63,12 +64,6 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final private Runnable mRequestFocus = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
mList.focusableViewAvailable(mList);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void bindPreferences() {
|
private void bindPreferences() {
|
||||||
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
|
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
|
||||||
if (localPreferenceScreen != null) {
|
if (localPreferenceScreen != null) {
|
||||||
@ -89,7 +84,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
|
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
|
||||||
}
|
}
|
||||||
|
|
||||||
mList = (ListView)listView;
|
mList = (ListView) listView;
|
||||||
if (mList == null) {
|
if (mList == null) {
|
||||||
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
|
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
|
||||||
}
|
}
|
||||||
@ -110,26 +105,17 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPreferencesFromIntent(Intent intent) {
|
private PreferenceScreen addPreferencesFromResource(int resId) {
|
||||||
requirePreferenceManager();
|
|
||||||
PreferenceScreen screen = inflateFromIntent(intent, getPreferenceScreen());
|
|
||||||
setPreferenceScreen(screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PreferenceScreen addPreferencesFromResource(int resId) {
|
|
||||||
requirePreferenceManager();
|
requirePreferenceManager();
|
||||||
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
|
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
|
||||||
setPreferenceScreen(screen);
|
setPreferenceScreen(screen);
|
||||||
|
|
||||||
for(int i = 0; i < screen.getPreferenceCount(); i++) {
|
for (int i = 0; i < screen.getPreferenceCount(); i++) {
|
||||||
Preference preference = screen.getPreference(i);
|
Preference preference = screen.getPreference(i);
|
||||||
if(preference instanceof PreferenceScreen && preference.getKey() != null) {
|
if (preference instanceof PreferenceScreen && preference.getKey() != null) {
|
||||||
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
preference.setOnPreferenceClickListener(preference1 -> {
|
||||||
@Override
|
onStartNewFragment(preference1.getKey());
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
return false;
|
||||||
onStartNewFragment(preference.getKey());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,19 +123,19 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Preference findPreference(CharSequence key) {
|
Preference findPreference(CharSequence key) {
|
||||||
if (mPreferenceManager == null) {
|
if (mPreferenceManager == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mPreferenceManager.findPreference(key);
|
return mPreferenceManager.findPreference(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListView getListView() {
|
private ListView getListView() {
|
||||||
ensureList();
|
ensureList();
|
||||||
return mList;
|
return mList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceManager getPreferenceManager() {
|
PreferenceManager getPreferenceManager() {
|
||||||
return mPreferenceManager;
|
return mPreferenceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +170,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
mPreferenceManager = createPreferenceManager();
|
mPreferenceManager = createPreferenceManager();
|
||||||
|
|
||||||
int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0);
|
int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0);
|
||||||
if(res != 0) {
|
if (res != 0) {
|
||||||
PreferenceScreen preferenceScreen = addPreferencesFromResource(res);
|
PreferenceScreen preferenceScreen = addPreferencesFromResource(res);
|
||||||
onInitPreferences(preferenceScreen);
|
onInitPreferences(preferenceScreen);
|
||||||
}
|
}
|
||||||
@ -226,7 +212,9 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
dispatchActivityStop();
|
dispatchActivityStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access methods with visibility private **/
|
/**
|
||||||
|
* Access methods with visibility private
|
||||||
|
**/
|
||||||
|
|
||||||
private PreferenceManager createPreferenceManager() {
|
private PreferenceManager createPreferenceManager() {
|
||||||
try {
|
try {
|
||||||
@ -248,7 +236,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPreferenceScreen(PreferenceScreen preferenceScreen) {
|
void setPreferenceScreen(PreferenceScreen preferenceScreen) {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
@ -294,19 +282,8 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
|
||||||
private void setFragment(PreferenceFragment preferenceFragment) {
|
PreferenceScreen preferenceScreen;
|
||||||
try {
|
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("setFragment", PreferenceFragment.class);
|
|
||||||
m.setAccessible(true);
|
|
||||||
m.invoke(mPreferenceManager, preferenceFragment);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
|
|
||||||
PreferenceScreen preferenceScreen ;
|
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
@ -317,18 +294,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|||||||
return preferenceScreen;
|
return preferenceScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
|
|
||||||
PreferenceScreen preferenceScreen ;
|
|
||||||
try {
|
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
|
|
||||||
m.setAccessible(true);
|
|
||||||
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, queryIntent, rootPreferences);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return preferenceScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onInitPreferences(PreferenceScreen preferenceScreen);
|
protected abstract void onInitPreferences(PreferenceScreen preferenceScreen);
|
||||||
|
|
||||||
protected abstract void onStartNewFragment(String name);
|
protected abstract void onStartNewFragment(String name);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,16 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.net.Uri;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.adapter.ArtistAdapter;
|
import net.nullsum.audinaut.adapter.ArtistAdapter;
|
||||||
import net.nullsum.audinaut.adapter.EntryGridAdapter;
|
import net.nullsum.audinaut.adapter.EntryGridAdapter;
|
||||||
@ -28,26 +20,30 @@ import net.nullsum.audinaut.domain.Artist;
|
|||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.SearchCritera;
|
import net.nullsum.audinaut.domain.SearchCritera;
|
||||||
import net.nullsum.audinaut.domain.SearchResult;
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
|
||||||
import net.nullsum.audinaut.util.BackgroundTask;
|
import net.nullsum.audinaut.util.BackgroundTask;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.TabBackgroundTask;
|
import net.nullsum.audinaut.util.TabBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
|
public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
|
||||||
private static final String TAG = SearchFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final int MAX_ARTISTS = 20;
|
private static final int MAX_ARTISTS = 20;
|
||||||
private static final int MAX_ALBUMS = 20;
|
private static final int MAX_ALBUMS = 20;
|
||||||
private static final int MAX_SONGS = 50;
|
private static final int MAX_SONGS = 50;
|
||||||
private static final int MIN_CLOSENESS = 1;
|
private static final int MIN_CLOSENESS = 1;
|
||||||
|
|
||||||
protected RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
protected SearchAdapter adapter;
|
private SearchAdapter adapter;
|
||||||
protected boolean largeAlbums = false;
|
private boolean largeAlbums = false;
|
||||||
|
|
||||||
private SearchResult searchResult;
|
private SearchResult searchResult;
|
||||||
private boolean skipSearch = false;
|
private boolean skipSearch = false;
|
||||||
@ -62,7 +58,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if(savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
|
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
}
|
}
|
||||||
largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
|
largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
|
||||||
@ -79,16 +75,16 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
||||||
setTitle(R.string.search_title);
|
setTitle(R.string.search_title);
|
||||||
|
|
||||||
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
refreshLayout = rootView.findViewById(R.id.refresh_layout);
|
||||||
refreshLayout.setEnabled(false);
|
refreshLayout.setEnabled(false);
|
||||||
|
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
recyclerView = rootView.findViewById(R.id.fragment_recycler);
|
||||||
setupLayoutManager(recyclerView, largeAlbums);
|
setupLayoutManager(recyclerView, largeAlbums);
|
||||||
|
|
||||||
registerForContextMenu(recyclerView);
|
registerForContextMenu(recyclerView);
|
||||||
context.onNewIntent(context.getIntent());
|
context.onNewIntent(context.getIntent());
|
||||||
|
|
||||||
if(searchResult != null) {
|
if (searchResult != null) {
|
||||||
skipSearch = true;
|
skipSearch = true;
|
||||||
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
|
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
|
||||||
}
|
}
|
||||||
@ -100,9 +96,9 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
||||||
boolean update = this.isOnlyVisible != isOnlyVisible;
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
||||||
super.setIsOnlyVisible(isOnlyVisible);
|
super.setIsOnlyVisible(isOnlyVisible);
|
||||||
if(update && adapter != null) {
|
if (update && adapter != null) {
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if (layoutManager instanceof GridLayoutManager) {
|
||||||
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +110,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
@Override
|
@Override
|
||||||
public int getSpanSize(int position) {
|
public int getSpanSize(int position) {
|
||||||
int viewType = adapter.getItemViewType(position);
|
int viewType = adapter.getItemViewType(position);
|
||||||
if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
|
if (viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
|
||||||
return gridLayoutManager.getSpanCount();
|
return gridLayoutManager.getSpanCount();
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@ -132,7 +128,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
||||||
if(item instanceof MusicDirectory.Entry && !Util.isOffline(context)) {
|
if (item instanceof MusicDirectory.Entry && !Util.isOffline(context)) {
|
||||||
menu.removeItem(R.id.song_menu_remove_playlist);
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
||||||
}
|
}
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
@ -157,7 +153,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
onAlbumSelected(entry, false);
|
onAlbumSelected(entry, false);
|
||||||
} else {
|
} else {
|
||||||
onSongSelected(entry, false, true, true, false);
|
onSongSelected(entry, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,8 +162,8 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
protected List<MusicDirectory.Entry> getSelectedEntries() {
|
protected List<MusicDirectory.Entry> getSelectedEntries() {
|
||||||
List<Serializable> selected = adapter.getSelected();
|
List<Serializable> selected = adapter.getSelected();
|
||||||
List<MusicDirectory.Entry> selectedMedia = new ArrayList<>();
|
List<MusicDirectory.Entry> selectedMedia = new ArrayList<>();
|
||||||
for(Serializable ser: selected) {
|
for (Serializable ser : selected) {
|
||||||
if(ser instanceof MusicDirectory.Entry) {
|
if (ser instanceof MusicDirectory.Entry) {
|
||||||
selectedMedia.add((MusicDirectory.Entry) ser);
|
selectedMedia.add((MusicDirectory.Entry) ser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +177,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void search(final String query, final boolean autoplay) {
|
public void search(final String query, final boolean autoplay) {
|
||||||
if(skipSearch) {
|
if (skipSearch) {
|
||||||
skipSearch = false;
|
skipSearch = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -207,7 +203,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
};
|
};
|
||||||
task.execute();
|
task.execute();
|
||||||
|
|
||||||
if(searchItem != null) {
|
if (searchItem != null) {
|
||||||
MenuItemCompat.collapseActionView(searchItem);
|
MenuItemCompat.collapseActionView(searchItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,7 +217,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||||
if(autoplay) {
|
if (autoplay) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
}
|
}
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
@ -235,7 +231,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
||||||
if(autoplay) {
|
if (autoplay) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
@ -243,16 +239,14 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
|
private void onSongSelected(MusicDirectory.Entry song, boolean append) {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if (downloadService != null) {
|
if (downloadService != null) {
|
||||||
if (!append) {
|
if (!append) {
|
||||||
downloadService.clear();
|
downloadService.clear();
|
||||||
}
|
}
|
||||||
downloadService.download(Arrays.asList(song), save, false, playNext, false);
|
downloadService.download(Collections.singletonList(song), false, false, false, false);
|
||||||
if (autoplay) {
|
downloadService.play(downloadService.size() - 1);
|
||||||
downloadService.play(downloadService.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
||||||
}
|
}
|
||||||
@ -262,30 +256,30 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
|
|||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
||||||
Artist artist = null;
|
Artist artist = null;
|
||||||
if(!searchResult.getArtists().isEmpty()) {
|
if (!searchResult.getArtists().isEmpty()) {
|
||||||
artist = searchResult.getArtists().get(0);
|
artist = searchResult.getArtists().get(0);
|
||||||
artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query));
|
artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
MusicDirectory.Entry album = null;
|
MusicDirectory.Entry album = null;
|
||||||
if(!searchResult.getAlbums().isEmpty()) {
|
if (!searchResult.getAlbums().isEmpty()) {
|
||||||
album = searchResult.getAlbums().get(0);
|
album = searchResult.getAlbums().get(0);
|
||||||
album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query));
|
album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
MusicDirectory.Entry song = null;
|
MusicDirectory.Entry song = null;
|
||||||
if(!searchResult.getSongs().isEmpty()) {
|
if (!searchResult.getSongs().isEmpty()) {
|
||||||
song = searchResult.getSongs().get(0);
|
song = searchResult.getSongs().get(0);
|
||||||
song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query));
|
song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(artist != null && (artist.getCloseness() <= MIN_CLOSENESS ||
|
if (artist != null && (artist.getCloseness() <= MIN_CLOSENESS ||
|
||||||
(album == null || artist.getCloseness() <= album.getCloseness()) &&
|
(album == null || artist.getCloseness() <= album.getCloseness()) &&
|
||||||
(song == null || artist.getCloseness() <= song.getCloseness()))) {
|
(song == null || artist.getCloseness() <= song.getCloseness()))) {
|
||||||
onArtistSelected(artist, true);
|
onArtistSelected(artist, true);
|
||||||
} else if(album != null && (album.getCloseness() <= MIN_CLOSENESS ||
|
} else if (album != null && (album.getCloseness() <= MIN_CLOSENESS ||
|
||||||
song == null || album.getCloseness() <= song.getCloseness())) {
|
song == null || album.getCloseness() <= song.getCloseness())) {
|
||||||
onAlbumSelected(album, true);
|
onAlbumSelected(album, true);
|
||||||
} else if(song != null) {
|
} else if (song != null) {
|
||||||
onSongSelected(song, false, false, true, false);
|
onSongSelected(song, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@ -29,7 +28,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> implements ArtistAdapter.OnMusicFolderChanged {
|
public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> implements ArtistAdapter.OnMusicFolderChanged {
|
||||||
private static final String TAG = SelectArtistFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
private List<MusicFolder> musicFolders = null;
|
private List<MusicFolder> musicFolders = null;
|
||||||
private List<Entry> entries;
|
private List<Entry> entries;
|
||||||
@ -44,7 +42,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
if(bundle != null) {
|
if (bundle != null) {
|
||||||
musicFolders = (List<MusicFolder>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
musicFolders = (List<MusicFolder>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
||||||
}
|
}
|
||||||
artist = true;
|
artist = true;
|
||||||
@ -59,8 +57,8 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if(args != null) {
|
if (args != null) {
|
||||||
if(args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) {
|
if (args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) {
|
||||||
groupId = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
groupId = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
||||||
groupName = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
groupName = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
||||||
|
|
||||||
@ -90,10 +88,10 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
||||||
SubsonicFragment fragment;
|
SubsonicFragment fragment;
|
||||||
if(item instanceof Artist) {
|
if (item instanceof Artist) {
|
||||||
Artist artist = (Artist) item;
|
Artist artist = (Artist) item;
|
||||||
|
|
||||||
if ((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || groupId != null) {
|
if ((Util.isFirstLevelArtist(context) || Util.isOffline(context)) || groupId != null) {
|
||||||
fragment = new SelectDirectoryFragment();
|
fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||||
@ -129,7 +127,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
super.onCreateOptionsMenu(menu, menuInflater);
|
super.onCreateOptionsMenu(menu, menuInflater);
|
||||||
|
|
||||||
if(Util.isOffline(context) || Util.isTagBrowsing(context) || groupId != null) {
|
if (Util.isOffline(context) || groupId != null) {
|
||||||
menu.removeItem(R.id.menu_first_level_artist);
|
menu.removeItem(R.id.menu_first_level_artist);
|
||||||
} else {
|
} else {
|
||||||
if (Util.isFirstLevelArtist(context)) {
|
if (Util.isFirstLevelArtist(context)) {
|
||||||
@ -145,7 +143,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(super.onOptionsItemSelected(item)) {
|
if (super.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,18 +164,8 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
@Override
|
@Override
|
||||||
public List<Serializable> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Serializable> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<Serializable> items;
|
List<Serializable> items;
|
||||||
if(groupId == null) {
|
if (groupId == null) {
|
||||||
if (!Util.isOffline(context) && !Util.isTagBrowsing(context)) {
|
musicFolders = null;
|
||||||
musicFolders = musicService.getMusicFolders(refresh, context, listener);
|
|
||||||
|
|
||||||
// Hide folders option if there is only one
|
|
||||||
if (musicFolders.size() == 1) {
|
|
||||||
musicFolders = null;
|
|
||||||
Util.setSelectedMusicFolderId(context, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
musicFolders = null;
|
|
||||||
}
|
|
||||||
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
|
|
||||||
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
|
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
|
||||||
@ -191,7 +179,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
List<Artist> artists = new ArrayList<>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
items = new ArrayList<>();
|
items = new ArrayList<>();
|
||||||
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
|
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
|
||||||
for(Entry entry: dir.getChildren(true, false)) {
|
for (Entry entry : dir.getChildren(true, false)) {
|
||||||
Artist artist = new Artist();
|
Artist artist = new Artist();
|
||||||
artist.setId(entry.getId());
|
artist.setId(entry.getId());
|
||||||
artist.setName(entry.getTitle());
|
artist.setName(entry.getTitle());
|
||||||
@ -204,9 +192,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
items.addAll(indexes.getArtists());
|
items.addAll(indexes.getArtists());
|
||||||
|
|
||||||
entries = dir.getChildren(false, true);
|
entries = dir.getChildren(false, true);
|
||||||
for(Entry entry: entries) {
|
items.addAll(entries);
|
||||||
items.add(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
@ -221,7 +207,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
public void setEmpty(boolean empty) {
|
public void setEmpty(boolean empty) {
|
||||||
super.setEmpty(empty);
|
super.setEmpty(empty);
|
||||||
|
|
||||||
if(empty && !Util.isOffline(context)) {
|
if (empty && !Util.isOffline(context)) {
|
||||||
objects.clear();
|
objects.clear();
|
||||||
recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this));
|
recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this));
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
@ -244,7 +230,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||||||
String startMusicFolderId = Util.getSelectedMusicFolderId(context);
|
String startMusicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
||||||
|
|
||||||
if(!Util.equals(startMusicFolderId, musicFolderId)) {
|
if (!Util.equals(startMusicFolderId, musicFolderId)) {
|
||||||
Util.setSelectedMusicFolderId(context, musicFolderId);
|
Util.setSelectedMusicFolderId(context, musicFolderId);
|
||||||
context.invalidate();
|
context.invalidate();
|
||||||
}
|
}
|
||||||
|
@ -1,74 +1,57 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.method.LinkMovementMethod;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.adapter.AlphabeticalAlbumAdapter;
|
import net.nullsum.audinaut.adapter.AlphabeticalAlbumAdapter;
|
||||||
import net.nullsum.audinaut.adapter.EntryInfiniteGridAdapter;
|
|
||||||
import net.nullsum.audinaut.adapter.EntryGridAdapter;
|
import net.nullsum.audinaut.adapter.EntryGridAdapter;
|
||||||
|
import net.nullsum.audinaut.adapter.EntryInfiniteGridAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.service.CachedMusicService;
|
import net.nullsum.audinaut.service.CachedMusicService;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
|
||||||
import net.nullsum.audinaut.util.DrawableTint;
|
|
||||||
import net.nullsum.audinaut.util.ImageLoader;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
import net.nullsum.audinaut.service.OfflineException;
|
import net.nullsum.audinaut.service.OfflineException;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.LoadingTask;
|
import net.nullsum.audinaut.util.LoadingTask;
|
||||||
import net.nullsum.audinaut.util.Pair;
|
import net.nullsum.audinaut.util.Pair;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.TabBackgroundTask;
|
import net.nullsum.audinaut.util.TabBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.UpdateHelper;
|
|
||||||
import net.nullsum.audinaut.util.UserUtil;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
import net.nullsum.audinaut.view.GridSpacingDecoration;
|
|
||||||
import net.nullsum.audinaut.view.MyLeadingMarginSpan2;
|
|
||||||
import net.nullsum.audinaut.view.RecyclingImageView;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
|
|
||||||
public class SelectDirectoryFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Entry> {
|
public class SelectDirectoryFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Entry> {
|
||||||
private static final String TAG = SelectDirectoryFragment.class.getSimpleName();
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private Entry directory;
|
||||||
|
private String playlistId;
|
||||||
|
private String playlistName;
|
||||||
|
private boolean playlistOwner;
|
||||||
|
private String albumListType;
|
||||||
|
private String albumListExtra;
|
||||||
|
private int albumListSize;
|
||||||
|
private boolean refreshListing = false;
|
||||||
|
private boolean restoredInstance = false;
|
||||||
|
private boolean lookupParent = false;
|
||||||
|
private boolean largeAlbums = false;
|
||||||
|
private boolean topTracks = false;
|
||||||
|
private String lookupEntry;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private FastScroller fastScroller;
|
private FastScroller fastScroller;
|
||||||
private EntryGridAdapter entryGridAdapter;
|
private EntryGridAdapter entryGridAdapter;
|
||||||
@ -76,27 +59,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
private List<Entry> entries;
|
private List<Entry> entries;
|
||||||
private LoadTask currentTask;
|
private LoadTask currentTask;
|
||||||
|
|
||||||
private SilentBackgroundTask updateCoverArtTask;
|
|
||||||
private ImageView coverArtView;
|
|
||||||
private Entry coverArtRep;
|
|
||||||
private String coverArtId;
|
|
||||||
|
|
||||||
String id;
|
|
||||||
String name;
|
|
||||||
Entry directory;
|
|
||||||
String playlistId;
|
|
||||||
String playlistName;
|
|
||||||
boolean playlistOwner;
|
|
||||||
String albumListType;
|
|
||||||
String albumListExtra;
|
|
||||||
int albumListSize;
|
|
||||||
boolean refreshListing = false;
|
|
||||||
boolean restoredInstance = false;
|
|
||||||
boolean lookupParent = false;
|
|
||||||
boolean largeAlbums = false;
|
|
||||||
boolean topTracks = false;
|
|
||||||
String lookupEntry;
|
|
||||||
|
|
||||||
public SelectDirectoryFragment() {
|
public SelectDirectoryFragment() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -104,10 +66,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
if(bundle != null) {
|
if (bundle != null) {
|
||||||
entries = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
entries = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
albums = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
albums = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
||||||
if(albums == null) {
|
if (albums == null) {
|
||||||
albums = new ArrayList<>();
|
albums = new ArrayList<>();
|
||||||
}
|
}
|
||||||
restoredInstance = true;
|
restoredInstance = true;
|
||||||
@ -124,14 +86,13 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if(args != null) {
|
if (args != null) {
|
||||||
id = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
id = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
||||||
name = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
name = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
||||||
directory = (Entry) args.getSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY);
|
directory = (Entry) args.getSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY);
|
||||||
playlistId = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
|
playlistId = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
|
||||||
playlistName = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME);
|
playlistName = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME);
|
||||||
playlistOwner = args.getBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, false);
|
playlistOwner = args.getBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, false);
|
||||||
Object shareObj = args.getSerializable(Constants.INTENT_EXTRA_NAME_SHARE);
|
|
||||||
albumListType = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
|
albumListType = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
|
||||||
albumListExtra = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA);
|
albumListExtra = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA);
|
||||||
albumListSize = args.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
|
albumListSize = args.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
|
||||||
@ -141,37 +102,37 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
topTracks = args.getBoolean(Constants.INTENT_EXTRA_TOP_TRACKS);
|
topTracks = args.getBoolean(Constants.INTENT_EXTRA_TOP_TRACKS);
|
||||||
|
|
||||||
String childId = args.getString(Constants.INTENT_EXTRA_NAME_CHILD_ID);
|
String childId = args.getString(Constants.INTENT_EXTRA_NAME_CHILD_ID);
|
||||||
if(childId != null) {
|
if (childId != null) {
|
||||||
id = childId;
|
id = childId;
|
||||||
lookupParent = true;
|
lookupParent = true;
|
||||||
}
|
}
|
||||||
if(entries == null) {
|
if (entries == null) {
|
||||||
entries = (List<Entry>) args.getSerializable(Constants.FRAGMENT_LIST);
|
entries = (List<Entry>) args.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
albums = (List<Entry>) args.getSerializable(Constants.FRAGMENT_LIST2);
|
albums = (List<Entry>) args.getSerializable(Constants.FRAGMENT_LIST2);
|
||||||
|
|
||||||
if(albums == null) {
|
if (albums == null) {
|
||||||
albums = new ArrayList<Entry>();
|
albums = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
||||||
|
|
||||||
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
refreshLayout = rootView.findViewById(R.id.refresh_layout);
|
||||||
refreshLayout.setOnRefreshListener(this);
|
refreshLayout.setOnRefreshListener(this);
|
||||||
|
|
||||||
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) {
|
if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) {
|
||||||
largeAlbums = true;
|
largeAlbums = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
recyclerView = rootView.findViewById(R.id.fragment_recycler);
|
||||||
recyclerView.setHasFixedSize(true);
|
recyclerView.setHasFixedSize(true);
|
||||||
fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller);
|
fastScroller = rootView.findViewById(R.id.fragment_fast_scroller);
|
||||||
setupScrollList(recyclerView);
|
setupScrollList(recyclerView);
|
||||||
setupLayoutManager(recyclerView, largeAlbums);
|
setupLayoutManager(recyclerView, largeAlbums);
|
||||||
|
|
||||||
if(entries == null) {
|
if (entries == null) {
|
||||||
if(primaryFragment || secondaryFragment) {
|
if (primaryFragment || secondaryFragment) {
|
||||||
load(false);
|
load(false);
|
||||||
} else {
|
} else {
|
||||||
invalidated = true;
|
invalidated = true;
|
||||||
@ -180,7 +141,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
finishLoading();
|
finishLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name != null) {
|
if (name != null) {
|
||||||
setTitle(name);
|
setTitle(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,9 +152,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
||||||
boolean update = this.isOnlyVisible != isOnlyVisible;
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
||||||
super.setIsOnlyVisible(isOnlyVisible);
|
super.setIsOnlyVisible(isOnlyVisible);
|
||||||
if(update && entryGridAdapter != null) {
|
if (update && entryGridAdapter != null) {
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if (layoutManager instanceof GridLayoutManager) {
|
||||||
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,18 +162,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(albumListType != null) {
|
if (albumListType != null) {
|
||||||
menuInflater.inflate(R.menu.select_album_list, menu);
|
menuInflater.inflate(R.menu.select_album_list, menu);
|
||||||
} else if(artist) {
|
} else if (artist) {
|
||||||
menuInflater.inflate(R.menu.select_album, menu);
|
menuInflater.inflate(R.menu.select_album, menu);
|
||||||
} else {
|
} else {
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.select_song_offline, menu);
|
menuInflater.inflate(R.menu.select_song_offline, menu);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
menuInflater.inflate(R.menu.select_song, menu);
|
menuInflater.inflate(R.menu.select_song, menu);
|
||||||
|
|
||||||
if(playlistId == null || !playlistOwner) {
|
if (playlistId == null || !playlistOwner) {
|
||||||
menu.removeItem(R.id.menu_remove_playlist);
|
menu.removeItem(R.id.menu_remove_playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,21 +194,22 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Entry entry) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Entry entry) {
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, entry);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, entry);
|
||||||
if(!Util.isOffline(context) && (playlistId == null || !playlistOwner)) {
|
if (!Util.isOffline(context) && (playlistId == null || !playlistOwner)) {
|
||||||
menu.removeItem(R.id.song_menu_remove_playlist);
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Entry> updateView, Entry entry) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Entry> updateView, Entry entry) {
|
||||||
if(onContextItemSelected(menuItem, entry)) {
|
if (onContextItemSelected(menuItem, entry)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.song_menu_remove_playlist:
|
case R.id.song_menu_remove_playlist:
|
||||||
removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(entries.indexOf(entry)));
|
removeFromPlaylist(playlistId, playlistName, Collections.singletonList(entries.indexOf(entry)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,12 +227,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
if ("newest".equals(albumListType)) {
|
if ("newest".equals(albumListType)) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
|
args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
|
||||||
}
|
}
|
||||||
if(!entry.isAlbum()) {
|
if (!entry.isAlbum()) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment, true);
|
replaceFragment(fragment);
|
||||||
} else {
|
} else {
|
||||||
onSongPress(entries, entry, albumListType == null);
|
onSongPress(entries, entry, albumListType == null);
|
||||||
}
|
}
|
||||||
@ -288,11 +249,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void load(boolean refresh) {
|
private void load(boolean refresh) {
|
||||||
if(refreshListing) {
|
if (refreshListing) {
|
||||||
refresh = true;
|
refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentTask != null) {
|
if (currentTask != null) {
|
||||||
currentTask.cancel();
|
currentTask.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,21 +270,21 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
private void getMusicDirectory(final String id, final String name, final boolean refresh) {
|
private void getMusicDirectory(final String id, final String name, final boolean refresh) {
|
||||||
setTitle(name);
|
setTitle(name);
|
||||||
|
|
||||||
new LoadTask(refresh) {
|
new LoadTask() {
|
||||||
@Override
|
@Override
|
||||||
protected MusicDirectory load(MusicService service) throws Exception {
|
protected MusicDirectory load(MusicService service) throws Exception {
|
||||||
MusicDirectory dir = getMusicDirectory(id, name, refresh, service, this);
|
MusicDirectory dir = getMusicDirectory(id, name, refresh, service, this);
|
||||||
|
|
||||||
if(lookupParent && dir.getParent() != null) {
|
if (lookupParent && dir.getParent() != null) {
|
||||||
dir = getMusicDirectory(dir.getParent(), name, refresh, service, this);
|
dir = getMusicDirectory(dir.getParent(), name, refresh, service, this);
|
||||||
|
|
||||||
// Update the fragment pointers so other stuff works correctly
|
// Update the fragment pointers so other stuff works correctly
|
||||||
SelectDirectoryFragment.this.id = dir.getId();
|
SelectDirectoryFragment.this.id = dir.getId();
|
||||||
SelectDirectoryFragment.this.name = dir.getName();
|
SelectDirectoryFragment.this.name = dir.getName();
|
||||||
} else if(id != null && directory == null && dir.getParent() != null && !artist) {
|
} else if (id != null && directory == null && dir.getParent() != null && !artist) {
|
||||||
MusicDirectory parentDir = getMusicDirectory(dir.getParent(), name, refresh, true, service, this);
|
MusicDirectory parentDir = getMusicDirectory(dir.getParent(), name, refresh, true, service, this);
|
||||||
for(Entry child: parentDir.getChildren()) {
|
for (Entry child : parentDir.getChildren()) {
|
||||||
if(id.equals(child.getId())) {
|
if (id.equals(child.getId())) {
|
||||||
directory = child;
|
directory = child;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -342,47 +303,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getRecursiveMusicDirectory(final String id, final String name, final boolean refresh) {
|
|
||||||
setTitle(name);
|
|
||||||
|
|
||||||
new LoadTask(refresh) {
|
|
||||||
@Override
|
|
||||||
protected MusicDirectory load(MusicService service) throws Exception {
|
|
||||||
MusicDirectory root = getMusicDirectory(id, name, refresh, service, this);
|
|
||||||
List<Entry> songs = new ArrayList<Entry>();
|
|
||||||
getSongsRecursively(root, songs);
|
|
||||||
root.replaceChildren(songs);
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getSongsRecursively(MusicDirectory parent, List<Entry> songs) throws Exception {
|
|
||||||
songs.addAll(parent.getChildren(false, true));
|
|
||||||
for (Entry dir : parent.getChildren(true, false)) {
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
|
||||||
|
|
||||||
MusicDirectory musicDirectory;
|
|
||||||
if(Util.isTagBrowsing(context) && !Util.isOffline(context)) {
|
|
||||||
musicDirectory = musicService.getAlbum(dir.getId(), dir.getTitle(), false, context, this);
|
|
||||||
} else {
|
|
||||||
musicDirectory = musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, context, this);
|
|
||||||
}
|
|
||||||
getSongsRecursively(musicDirectory, songs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Pair<MusicDirectory, Boolean> result) {
|
|
||||||
SelectDirectoryFragment.this.name = result.getFirst().getName();
|
|
||||||
setTitle(SelectDirectoryFragment.this.name);
|
|
||||||
super.done(result);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getPlaylist(final String playlistId, final String playlistName, final boolean refresh) {
|
private void getPlaylist(final String playlistId, final String playlistName, final boolean refresh) {
|
||||||
setTitle(playlistName);
|
setTitle(playlistName);
|
||||||
|
|
||||||
new LoadTask(refresh) {
|
new LoadTask() {
|
||||||
@Override
|
@Override
|
||||||
protected MusicDirectory load(MusicService service) throws Exception {
|
protected MusicDirectory load(MusicService service) throws Exception {
|
||||||
return service.getPlaylist(refresh, playlistId, playlistName, context, this);
|
return service.getPlaylist(refresh, playlistId, playlistName, context, this);
|
||||||
@ -397,11 +321,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
setTitle(R.string.main_albums_recent);
|
setTitle(R.string.main_albums_recent);
|
||||||
} else if ("frequent".equals(albumListType)) {
|
} else if ("frequent".equals(albumListType)) {
|
||||||
setTitle(R.string.main_albums_frequent);
|
setTitle(R.string.main_albums_frequent);
|
||||||
} else if("genres".equals(albumListType) || "years".equals(albumListType)) {
|
} else if ("genres".equals(albumListType) || "years".equals(albumListType)) {
|
||||||
setTitle(albumListExtra);
|
setTitle(albumListExtra);
|
||||||
} else if("alphabeticalByName".equals(albumListType)) {
|
} else if ("alphabeticalByName".equals(albumListType)) {
|
||||||
setTitle(R.string.main_albums_alphabetical);
|
setTitle(R.string.main_albums_alphabetical);
|
||||||
} if (MainFragment.SONGS_NEWEST.equals(albumListType)) {
|
}
|
||||||
|
if (MainFragment.SONGS_NEWEST.equals(albumListType)) {
|
||||||
setTitle(R.string.main_songs_newest);
|
setTitle(R.string.main_songs_newest);
|
||||||
} else if (MainFragment.SONGS_TOP_PLAYED.equals(albumListType)) {
|
} else if (MainFragment.SONGS_TOP_PLAYED.equals(albumListType)) {
|
||||||
setTitle(R.string.main_songs_top_played);
|
setTitle(R.string.main_songs_top_played);
|
||||||
@ -411,19 +336,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
setTitle(R.string.main_songs_frequent);
|
setTitle(R.string.main_songs_frequent);
|
||||||
}
|
}
|
||||||
|
|
||||||
new LoadTask(true) {
|
new LoadTask() {
|
||||||
@Override
|
@Override
|
||||||
protected MusicDirectory load(MusicService service) throws Exception {
|
protected MusicDirectory load(MusicService service) throws Exception {
|
||||||
MusicDirectory result;
|
MusicDirectory result;
|
||||||
if("genres".equals(albumListType) || "years".equals(albumListType)) {
|
if ("genres".equals(albumListType) || "years".equals(albumListType)) {
|
||||||
result = service.getAlbumList(albumListType, albumListExtra, size, 0, refresh, context, this);
|
result = service.getAlbumList(albumListType, albumListExtra, size, 0, refresh, context, this);
|
||||||
if(result.getChildrenSize() == 0 && "genres".equals(albumListType)) {
|
if (result.getChildrenSize() == 0 && "genres".equals(albumListType)) {
|
||||||
SelectDirectoryFragment.this.albumListType = "genres-songs";
|
SelectDirectoryFragment.this.albumListType = "genres-songs";
|
||||||
result = service.getSongsByGenre(albumListExtra, size, 0, context, this);
|
result = service.getSongsByGenre(albumListExtra, size, 0, context, this);
|
||||||
}
|
}
|
||||||
} else if("genres".equals(albumListType) || "genres-songs".equals(albumListType)) {
|
} else if ("genres".equals(albumListType) || "genres-songs".equals(albumListType)) {
|
||||||
result = service.getSongsByGenre(albumListExtra, size, 0, context, this);
|
result = service.getSongsByGenre(albumListExtra, size, 0, context, this);
|
||||||
} else if(albumListType.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
|
} else if (albumListType.contains(MainFragment.SONGS_LIST_PREFIX)) {
|
||||||
result = service.getSongList(albumListType, size, 0, context, this);
|
result = service.getSongList(albumListType, size, 0, context, this);
|
||||||
} else {
|
} else {
|
||||||
result = service.getAlbumList(albumListType, size, 0, refresh, context, this);
|
result = service.getAlbumList(albumListType, size, 0, refresh, context, this);
|
||||||
@ -433,58 +358,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class LoadTask extends TabBackgroundTask<Pair<MusicDirectory, Boolean>> {
|
|
||||||
private boolean refresh;
|
|
||||||
|
|
||||||
public LoadTask(boolean refresh) {
|
|
||||||
super(SelectDirectoryFragment.this);
|
|
||||||
this.refresh = refresh;
|
|
||||||
|
|
||||||
currentTask = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract MusicDirectory load(MusicService service) throws Exception;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pair<MusicDirectory, Boolean> doInBackground() throws Throwable {
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
|
||||||
MusicDirectory dir = load(musicService);
|
|
||||||
|
|
||||||
albums = dir.getChildren(true, false);
|
|
||||||
entries = dir.getChildren();
|
|
||||||
|
|
||||||
// This isn't really an artist if no albums on it!
|
|
||||||
if(albums.size() == 0) {
|
|
||||||
artist = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Pair<>(dir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Pair<MusicDirectory, Boolean> result) {
|
|
||||||
finishLoading();
|
|
||||||
currentTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateCache(int changeCode) {
|
|
||||||
if(entryGridAdapter != null && changeCode == CachedMusicService.CACHE_UPDATE_LIST) {
|
|
||||||
entryGridAdapter.notifyDataSetChanged();
|
|
||||||
} else if(changeCode == CachedMusicService.CACHE_UPDATE_METADATA) {
|
|
||||||
if(coverArtView != null && coverArtRep != null && !Util.equals(coverArtRep.getCoverArt(), coverArtId)) {
|
|
||||||
synchronized (coverArtRep) {
|
|
||||||
if (updateCoverArtTask != null && updateCoverArtTask.isRunning()) {
|
|
||||||
updateCoverArtTask.cancel();
|
|
||||||
}
|
|
||||||
updateCoverArtTask = getImageLoader().loadImage(coverArtView, coverArtRep, false, true);
|
|
||||||
coverArtId = coverArtRep.getCoverArt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter<Entry> getCurrentAdapter() {
|
public SectionAdapter<Entry> getCurrentAdapter() {
|
||||||
return entryGridAdapter;
|
return entryGridAdapter;
|
||||||
@ -496,7 +369,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
public int getSpanSize(int position) {
|
public int getSpanSize(int position) {
|
||||||
int viewType = entryGridAdapter.getItemViewType(position);
|
int viewType = entryGridAdapter.getItemViewType(position);
|
||||||
if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) {
|
if (viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) {
|
||||||
return gridLayoutManager.getSpanCount();
|
return gridLayoutManager.getSpanCount();
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@ -507,19 +380,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
|
|
||||||
private void finishLoading() {
|
private void finishLoading() {
|
||||||
boolean validData = !entries.isEmpty() || !albums.isEmpty();
|
boolean validData = !entries.isEmpty() || !albums.isEmpty();
|
||||||
if(!validData) {
|
if (!validData) {
|
||||||
setEmpty(true);
|
setEmpty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(validData) {
|
if (validData) {
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(albumListType == null) {
|
if (albumListType == null) {
|
||||||
entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums);
|
entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums);
|
||||||
entryGridAdapter.setRemoveFromPlaylist(playlistId != null);
|
entryGridAdapter.setRemoveFromPlaylist(playlistId != null);
|
||||||
} else {
|
} else {
|
||||||
if("alphabeticalByName".equals(albumListType)) {
|
if ("alphabeticalByName".equals(albumListType)) {
|
||||||
entryGridAdapter = new AlphabeticalAlbumAdapter(context, entries, getImageLoader(), largeAlbums);
|
entryGridAdapter = new AlphabeticalAlbumAdapter(context, entries, getImageLoader(), largeAlbums);
|
||||||
} else {
|
} else {
|
||||||
entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums);
|
entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums);
|
||||||
@ -530,10 +403,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
infiniteGridAdapter.setData(albumListType, albumListExtra, albumListSize);
|
infiniteGridAdapter.setData(albumListType, albumListExtra, albumListSize);
|
||||||
|
|
||||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
@Override
|
|
||||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
|
||||||
super.onScrollStateChanged(recyclerView, newState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||||
@ -542,15 +411,15 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
int totalItemCount = layoutManager.getItemCount();
|
int totalItemCount = layoutManager.getItemCount();
|
||||||
int lastVisibleItem;
|
int lastVisibleItem;
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if (layoutManager instanceof GridLayoutManager) {
|
||||||
lastVisibleItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
|
lastVisibleItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
|
||||||
} else if(layoutManager instanceof LinearLayoutManager) {
|
} else if (layoutManager instanceof LinearLayoutManager) {
|
||||||
lastVisibleItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
|
lastVisibleItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) {
|
if (totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) {
|
||||||
infiniteGridAdapter.loadMore();
|
infiniteGridAdapter.loadMore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,17 +427,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}
|
}
|
||||||
entryGridAdapter.setOnItemClickedListener(this);
|
entryGridAdapter.setOnItemClickedListener(this);
|
||||||
// Always show artist if this is not a artist we are viewing
|
// Always show artist if this is not a artist we are viewing
|
||||||
if(!artist) {
|
if (!artist) {
|
||||||
entryGridAdapter.setShowArtist(true);
|
entryGridAdapter.setShowArtist();
|
||||||
}
|
}
|
||||||
if(topTracks) {
|
if (topTracks) {
|
||||||
entryGridAdapter.setShowAlbum(true);
|
entryGridAdapter.setShowAlbum();
|
||||||
}
|
}
|
||||||
|
|
||||||
int scrollToPosition = -1;
|
int scrollToPosition = -1;
|
||||||
if(lookupEntry != null) {
|
if (lookupEntry != null) {
|
||||||
for(int i = 0; i < entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
if(lookupEntry.equals(entries.get(i).getTitle())) {
|
if (lookupEntry.equals(entries.get(i).getTitle())) {
|
||||||
scrollToPosition = i;
|
scrollToPosition = i;
|
||||||
entryGridAdapter.addSelected(entries.get(i));
|
entryGridAdapter.addSelected(entries.get(i));
|
||||||
lookupEntry = null;
|
lookupEntry = null;
|
||||||
@ -581,7 +450,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
fastScroller.attachRecyclerView(recyclerView);
|
fastScroller.attachRecyclerView(recyclerView);
|
||||||
context.supportInvalidateOptionsMenu();
|
context.supportInvalidateOptionsMenu();
|
||||||
|
|
||||||
if(scrollToPosition != -1) {
|
if (scrollToPosition != -1) {
|
||||||
recyclerView.scrollToPosition(scrollToPosition);
|
recyclerView.scrollToPosition(scrollToPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,30 +464,31 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
protected void playNow(final boolean shuffle, final boolean append, final boolean playNext) {
|
protected void playNow(final boolean shuffle, final boolean append, final boolean playNext) {
|
||||||
List<Entry> songs = getSelectedEntries();
|
List<Entry> songs = getSelectedEntries();
|
||||||
if(!songs.isEmpty()) {
|
if (!songs.isEmpty()) {
|
||||||
download(songs, append, false, !append, playNext, shuffle);
|
download(songs, append, !append, playNext, shuffle);
|
||||||
entryGridAdapter.clearSelected();
|
entryGridAdapter.clearSelected();
|
||||||
} else {
|
} else {
|
||||||
playAll(shuffle, append, playNext);
|
playAll(shuffle, append, playNext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void playAll(final boolean shuffle, final boolean append, final boolean playNext) {
|
private void playAll(final boolean shuffle, final boolean append, final boolean playNext) {
|
||||||
boolean hasSubFolders = albums != null && !albums.isEmpty();
|
boolean hasSubFolders = albums != null && !albums.isEmpty();
|
||||||
|
|
||||||
if (hasSubFolders && id != null) {
|
if (hasSubFolders && id != null) {
|
||||||
downloadRecursively(id, false, append, !append, shuffle, false, playNext);
|
downloadRecursively(id, false, append, !append, shuffle, false, playNext);
|
||||||
} else if(hasSubFolders && albumListType != null) {
|
} else if (hasSubFolders && albumListType != null) {
|
||||||
downloadRecursively(albums, shuffle, append, playNext);
|
downloadRecursively(albums, shuffle, append, playNext);
|
||||||
} else {
|
} else {
|
||||||
download(entries, append, false, !append, playNext, shuffle);
|
download(entries, append, !append, playNext, shuffle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Integer> getSelectedIndexes() {
|
private List<Integer> getSelectedIndexes() {
|
||||||
List<Entry> selected = entryGridAdapter.getSelected();
|
List<Entry> selected = entryGridAdapter.getSelected();
|
||||||
List<Integer> indexes = new ArrayList<Integer>();
|
List<Integer> indexes = new ArrayList<>();
|
||||||
|
|
||||||
for(Entry entry: selected) {
|
for (Entry entry : selected) {
|
||||||
indexes.add(entries.indexOf(entry));
|
indexes.add(entries.indexOf(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,28 +498,29 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
@Override
|
@Override
|
||||||
protected void downloadBackground(final boolean save) {
|
protected void downloadBackground(final boolean save) {
|
||||||
List<Entry> songs = getSelectedEntries();
|
List<Entry> songs = getSelectedEntries();
|
||||||
if(playlistId != null) {
|
if (playlistId != null) {
|
||||||
songs = entries;
|
songs = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(songs.isEmpty()) {
|
if (songs.isEmpty()) {
|
||||||
// Get both songs and albums
|
// Get both songs and albums
|
||||||
downloadRecursively(id, save, false, false, false, true);
|
downloadRecursively(id, save, false, false, false, true, false);
|
||||||
} else {
|
} else {
|
||||||
downloadBackground(save, songs);
|
downloadBackground(save, songs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void downloadBackground(final boolean save, final List<Entry> entries) {
|
void downloadBackground(final boolean save, final List<Entry> entries) {
|
||||||
if (getDownloadService() == null) {
|
if (getDownloadService() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
warnIfStorageUnavailable();
|
warnIfStorageUnavailable();
|
||||||
RecursiveLoader onValid = new RecursiveLoader(context) {
|
new RecursiveLoader(context) {
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground() throws Throwable {
|
protected Boolean doInBackground() throws Throwable {
|
||||||
getSongsRecursively(entries, true);
|
getSongsRecursively(entries);
|
||||||
getDownloadService().downloadBackground(songs, save);
|
getDownloadService().downloadBackground(songs, save);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -662,16 +533,16 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void download(List<Entry> entries, boolean append, boolean save, boolean autoplay, boolean playNext, boolean shuffle) {
|
void download(List<Entry> entries, boolean append, boolean autoplay, boolean playNext, boolean shuffle) {
|
||||||
download(entries, append, save, autoplay, playNext, shuffle, playlistName, playlistId);
|
download(entries, append, autoplay, playNext, shuffle, playlistName, playlistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void delete() {
|
protected void delete() {
|
||||||
List<Entry> songs = getSelectedEntries();
|
List<Entry> songs = getSelectedEntries();
|
||||||
if(songs.isEmpty()) {
|
if (songs.isEmpty()) {
|
||||||
for(Entry entry: entries) {
|
for (Entry entry : entries) {
|
||||||
if(entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
deleteRecursively(entry);
|
deleteRecursively(entry);
|
||||||
} else {
|
} else {
|
||||||
songs.add(entry);
|
songs.add(entry);
|
||||||
@ -683,7 +554,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromPlaylist(final String id, final String name, final List<Integer> indexes) {
|
private void removeFromPlaylist(final String id, final String name, final List<Integer> indexes) {
|
||||||
new LoadingTask<Void>(context, true) {
|
new LoadingTask<Void>(context, true) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
@ -694,7 +565,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
for(Integer index: indexes) {
|
for (Integer index : indexes) {
|
||||||
entryGridAdapter.removeAt(index);
|
entryGridAdapter.removeAt(index);
|
||||||
}
|
}
|
||||||
Util.toast(context, context.getResources().getString(R.string.removed_playlist, indexes.size(), name));
|
Util.toast(context, context.getResources().getString(R.string.removed_playlist, indexes.size(), name));
|
||||||
@ -714,113 +585,43 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showTopTracks() {
|
private abstract class LoadTask extends TabBackgroundTask<Pair<MusicDirectory, Boolean>> {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
|
||||||
Bundle args = new Bundle(getArguments());
|
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_TOP_TRACKS, true);
|
|
||||||
fragment.setArguments(args);
|
|
||||||
|
|
||||||
replaceFragment(fragment, true);
|
public LoadTask() {
|
||||||
}
|
super(SelectDirectoryFragment.this);
|
||||||
|
|
||||||
private View createHeader() {
|
currentTask = this;
|
||||||
View header = LayoutInflater.from(context).inflate(R.layout.select_album_header, null, false);
|
|
||||||
|
|
||||||
setupCoverArt(header);
|
|
||||||
setupTextDisplay(header);
|
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCoverArt(View header) {
|
|
||||||
setupCoverArtImpl((RecyclingImageView) header.findViewById(R.id.select_album_art));
|
|
||||||
}
|
|
||||||
private void setupCoverArtImpl(RecyclingImageView coverArtView) {
|
|
||||||
final ImageLoader imageLoader = getImageLoader();
|
|
||||||
|
|
||||||
if(entries.size() > 0) {
|
|
||||||
coverArtRep = null;
|
|
||||||
this.coverArtView = coverArtView;
|
|
||||||
for (int i = 0; (i < 3) && (coverArtRep == null || coverArtRep.getCoverArt() == null); i++) {
|
|
||||||
coverArtRep = entries.get(random.nextInt(entries.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
coverArtView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (coverArtRep == null || coverArtRep.getCoverArt() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
ImageView fullScreenView = new ImageView(context);
|
|
||||||
imageLoader.loadImage(fullScreenView, coverArtRep, true, true);
|
|
||||||
builder.setCancelable(true);
|
|
||||||
|
|
||||||
AlertDialog imageDialog = builder.create();
|
|
||||||
// Set view here with unecessary 0's to remove top/bottom border
|
|
||||||
imageDialog.setView(fullScreenView, 0, 0, 0, 0);
|
|
||||||
imageDialog.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
synchronized (coverArtRep) {
|
|
||||||
coverArtId = coverArtRep.getCoverArt();
|
|
||||||
updateCoverArtTask = imageLoader.loadImage(coverArtView, coverArtRep, false, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coverArtView.setOnInvalidated(new RecyclingImageView.OnInvalidated() {
|
protected abstract MusicDirectory load(MusicService service) throws Exception;
|
||||||
@Override
|
|
||||||
public void onInvalidated(RecyclingImageView imageView) {
|
@Override
|
||||||
setupCoverArtImpl(imageView);
|
protected Pair<MusicDirectory, Boolean> doInBackground() throws Throwable {
|
||||||
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
|
MusicDirectory dir = load(musicService);
|
||||||
|
|
||||||
|
albums = dir.getChildren(true, false);
|
||||||
|
entries = dir.getChildren();
|
||||||
|
|
||||||
|
// This isn't really an artist if no albums on it!
|
||||||
|
if (albums.size() == 0) {
|
||||||
|
artist = false;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
return new Pair<>(dir, true);
|
||||||
private void setupTextDisplay(final View header) {
|
|
||||||
final TextView titleView = (TextView) header.findViewById(R.id.select_album_title);
|
|
||||||
if(playlistName != null) {
|
|
||||||
titleView.setText(playlistName);
|
|
||||||
} else if(name != null) {
|
|
||||||
titleView.setText(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int songCount = 0;
|
@Override
|
||||||
|
protected void done(Pair<MusicDirectory, Boolean> result) {
|
||||||
Set<String> artists = new HashSet<String>();
|
finishLoading();
|
||||||
Set<Integer> years = new HashSet<Integer>();
|
currentTask = null;
|
||||||
Integer totalDuration = 0;
|
|
||||||
for (Entry entry : entries) {
|
|
||||||
if (!entry.isDirectory()) {
|
|
||||||
songCount++;
|
|
||||||
if (entry.getArtist() != null) {
|
|
||||||
artists.add(entry.getArtist());
|
|
||||||
}
|
|
||||||
if(entry.getYear() != null) {
|
|
||||||
years.add(entry.getYear());
|
|
||||||
}
|
|
||||||
Integer duration = entry.getDuration();
|
|
||||||
if(duration != null) {
|
|
||||||
totalDuration += duration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final TextView artistView = (TextView) header.findViewById(R.id.select_album_artist);
|
@Override
|
||||||
if (artists.size() == 1) {
|
public void updateCache(int changeCode) {
|
||||||
String artistText = artists.iterator().next();
|
if (entryGridAdapter != null && changeCode == CachedMusicService.CACHE_UPDATE_LIST) {
|
||||||
if(years.size() == 1) {
|
entryGridAdapter.notifyDataSetChanged();
|
||||||
artistText += " - " + years.iterator().next();
|
|
||||||
}
|
}
|
||||||
artistView.setText(artistText);
|
|
||||||
artistView.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
artistView.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView songCountView = (TextView) header.findViewById(R.id.select_album_song_count);
|
|
||||||
TextView songLengthView = (TextView) header.findViewById(R.id.select_album_song_length);
|
|
||||||
String s = context.getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount);
|
|
||||||
songCountView.setText(s.toUpperCase());
|
|
||||||
songLengthView.setText(Util.formatDuration(totalDuration));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,17 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
import net.nullsum.audinaut.adapter.GenreAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.adapter.GenreAdapter;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
|
public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
|
||||||
private static final String TAG = SelectGenreFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
@ -68,7 +67,8 @@ public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Genre> updateView, Genre item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Genre> updateView, Genre item) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Genre> updateView, Genre item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Genre> updateView, Genre item) {
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -13,30 +10,26 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
import net.nullsum.audinaut.adapter.PlaylistAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
import net.nullsum.audinaut.service.OfflineException;
|
import net.nullsum.audinaut.service.OfflineException;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import net.nullsum.audinaut.util.SyncUtil;
|
|
||||||
import net.nullsum.audinaut.util.CacheCleaner;
|
import net.nullsum.audinaut.util.CacheCleaner;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.LoadingTask;
|
import net.nullsum.audinaut.util.LoadingTask;
|
||||||
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
import net.nullsum.audinaut.util.SyncUtil;
|
||||||
import net.nullsum.audinaut.util.UserUtil;
|
import net.nullsum.audinaut.util.UserUtil;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import net.nullsum.audinaut.adapter.PlaylistAdapter;
|
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
||||||
private static final String TAG = SelectPlaylistFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
@ -50,11 +43,10 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Playlist> updateView, Playlist playlist) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Playlist> updateView, Playlist playlist) {
|
||||||
if (Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.select_playlist_context_offline, menu);
|
menuInflater.inflate(R.menu.select_playlist_context_offline, menu);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
menuInflater.inflate(R.menu.select_playlist_context, menu);
|
menuInflater.inflate(R.menu.select_playlist_context, menu);
|
||||||
|
|
||||||
if(playlist.getPublic() != null && playlist.getPublic() == true && playlist.getId().indexOf(".m3u") == -1 && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) {
|
if (playlist.getPublic() != null && playlist.getPublic() && !playlist.getId().contains(".m3u") && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) {
|
||||||
menu.removeItem(R.id.playlist_update_info);
|
menu.removeItem(R.id.playlist_update_info);
|
||||||
menu.removeItem(R.id.playlist_menu_delete);
|
menu.removeItem(R.id.playlist_menu_delete);
|
||||||
}
|
}
|
||||||
@ -67,11 +59,10 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Playlist> updateView, Playlist playlist) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Playlist> updateView, Playlist playlist) {
|
||||||
SubsonicFragment fragment;
|
SubsonicFragment fragment;
|
||||||
Bundle args;
|
Bundle args;
|
||||||
FragmentTransaction trans;
|
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.playlist_menu_download:
|
case R.id.playlist_menu_download:
|
||||||
downloadPlaylist(playlist.getId(), playlist.getName(), false, true, false, false, true);
|
downloadPlaylist(playlist.getId(), playlist.getName());
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_menu_play_now:
|
case R.id.playlist_menu_play_now:
|
||||||
fragment = new SelectDirectoryFragment();
|
fragment = new SelectDirectoryFragment();
|
||||||
@ -118,8 +109,8 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
List<Playlist> mine = new ArrayList<>();
|
List<Playlist> mine = new ArrayList<>();
|
||||||
|
|
||||||
String currentUsername = UserUtil.getCurrentUsername(context);
|
String currentUsername = UserUtil.getCurrentUsername(context);
|
||||||
for(Playlist playlist: playlists) {
|
for (Playlist playlist : playlists) {
|
||||||
if(playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) {
|
if (playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) {
|
||||||
mine.add(playlist);
|
mine.add(playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +121,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
@Override
|
@Override
|
||||||
public List<Playlist> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Playlist> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<Playlist> playlists = musicService.getPlaylists(refresh, context, listener);
|
List<Playlist> playlists = musicService.getPlaylists(refresh, context, listener);
|
||||||
if(!Util.isOffline(context) && refresh) {
|
if (!Util.isOffline(context) && refresh) {
|
||||||
new CacheCleaner(context, getDownloadService()).cleanPlaylists(playlists);
|
new CacheCleaner(context, getDownloadService()).cleanPlaylists(playlists);
|
||||||
}
|
}
|
||||||
return playlists;
|
return playlists;
|
||||||
@ -147,7 +138,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||||
if((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().indexOf(".m3u") != -1)) {
|
if ((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().contains(".m3u"))) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, true);
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
@ -158,7 +149,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
@Override
|
@Override
|
||||||
public void onFinishRefresh() {
|
public void onFinishRefresh() {
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if(args != null) {
|
if (args != null) {
|
||||||
String playlistId = args.getString(Constants.INTENT_EXTRA_NAME_ID, null);
|
String playlistId = args.getString(Constants.INTENT_EXTRA_NAME_ID, null);
|
||||||
if (playlistId != null && objects != null) {
|
if (playlistId != null && objects != null) {
|
||||||
for (Playlist playlist : objects) {
|
for (Playlist playlist : objects) {
|
||||||
@ -172,38 +163,33 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void deletePlaylist(final Playlist playlist) {
|
private void deletePlaylist(final Playlist playlist) {
|
||||||
Util.confirmDialog(context, R.string.common_delete, playlist.getName(), new DialogInterface.OnClickListener() {
|
Util.confirmDialog(context, R.string.common_delete, playlist.getName(), (dialog, which) -> new LoadingTask<Void>(context, false) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new LoadingTask<Void>(context, false) {
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
@Override
|
musicService.deletePlaylist(playlist.getId(), context, null);
|
||||||
protected Void doInBackground() throws Throwable {
|
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
return null;
|
||||||
musicService.deletePlaylist(playlist.getId(), context, null);
|
|
||||||
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
adapter.removeItem(playlist);
|
|
||||||
Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void error(Throwable error) {
|
|
||||||
String msg;
|
|
||||||
if (error instanceof OfflineException) {
|
|
||||||
msg = getErrorMessage(error);
|
|
||||||
} else {
|
|
||||||
msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.toast(context, msg, false);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
protected void done(Void result) {
|
||||||
|
adapter.removeItem(playlist);
|
||||||
|
Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void error(Throwable error) {
|
||||||
|
String msg;
|
||||||
|
if (error instanceof OfflineException) {
|
||||||
|
msg = getErrorMessage(error);
|
||||||
|
} else {
|
||||||
|
msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.toast(context, msg, false);
|
||||||
|
}
|
||||||
|
}.execute());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayPlaylistInfo(final Playlist playlist) {
|
private void displayPlaylistInfo(final Playlist playlist) {
|
||||||
@ -213,12 +199,12 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
headers.add(R.string.details_title);
|
headers.add(R.string.details_title);
|
||||||
details.add(playlist.getName());
|
details.add(playlist.getName());
|
||||||
|
|
||||||
if(playlist.getOwner() != null) {
|
if (playlist.getOwner() != null) {
|
||||||
headers.add(R.string.details_owner);
|
headers.add(R.string.details_owner);
|
||||||
details.add(playlist.getOwner());
|
details.add(playlist.getOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getComment() != null) {
|
if (playlist.getComment() != null) {
|
||||||
headers.add(R.string.details_comments);
|
headers.add(R.string.details_comments);
|
||||||
details.add(playlist.getComment());
|
details.add(playlist.getComment());
|
||||||
}
|
}
|
||||||
@ -226,23 +212,23 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
headers.add(R.string.details_song_count);
|
headers.add(R.string.details_song_count);
|
||||||
details.add(playlist.getSongCount());
|
details.add(playlist.getSongCount());
|
||||||
|
|
||||||
if(playlist.getDuration() != null) {
|
if (playlist.getDuration() != null) {
|
||||||
headers.add(R.string.details_length);
|
headers.add(R.string.details_length);
|
||||||
details.add(Util.formatDuration(playlist.getDuration()));
|
details.add(Util.formatDuration(playlist.getDuration()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getPublic() != null) {
|
if (playlist.getPublic() != null) {
|
||||||
headers.add(R.string.details_public);
|
headers.add(R.string.details_public);
|
||||||
details.add(Util.formatBoolean(context, playlist.getPublic()));
|
details.add(Util.formatBoolean(context, playlist.getPublic()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getCreated() != null) {
|
if (playlist.getCreated() != null) {
|
||||||
headers.add(R.string.details_created);
|
headers.add(R.string.details_created);
|
||||||
|
|
||||||
DateFormat dateFormat = DateFormat.getDateInstance();
|
DateFormat dateFormat = DateFormat.getDateInstance();
|
||||||
details.add(dateFormat.format(playlist.getCreated()));
|
details.add(dateFormat.format(playlist.getCreated()));
|
||||||
}
|
}
|
||||||
if(playlist.getChanged() != null) {
|
if (playlist.getChanged() != null) {
|
||||||
headers.add(R.string.details_updated);
|
headers.add(R.string.details_updated);
|
||||||
|
|
||||||
DateFormat dateFormat = DateFormat.getDateInstance();
|
DateFormat dateFormat = DateFormat.getDateInstance();
|
||||||
@ -254,93 +240,59 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
|||||||
|
|
||||||
private void updatePlaylistInfo(final Playlist playlist) {
|
private void updatePlaylistInfo(final Playlist playlist) {
|
||||||
View dialogView = context.getLayoutInflater().inflate(R.layout.update_playlist, null);
|
View dialogView = context.getLayoutInflater().inflate(R.layout.update_playlist, null);
|
||||||
final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_playlist_name);
|
final EditText nameBox = dialogView.findViewById(R.id.get_playlist_name);
|
||||||
final EditText commentBox = (EditText)dialogView.findViewById(R.id.get_playlist_comment);
|
final EditText commentBox = dialogView.findViewById(R.id.get_playlist_comment);
|
||||||
final CheckBox publicBox = (CheckBox)dialogView.findViewById(R.id.get_playlist_public);
|
final CheckBox publicBox = dialogView.findViewById(R.id.get_playlist_public);
|
||||||
|
|
||||||
nameBox.setText(playlist.getName());
|
nameBox.setText(playlist.getName());
|
||||||
commentBox.setText(playlist.getComment());
|
commentBox.setText(playlist.getComment());
|
||||||
Boolean pub = playlist.getPublic();
|
Boolean pub = playlist.getPublic();
|
||||||
if(pub == null) {
|
if (pub == null) {
|
||||||
publicBox.setEnabled(false);
|
publicBox.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
publicBox.setChecked(pub);
|
publicBox.setChecked(pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
.setTitle(R.string.playlist_update_info)
|
.setTitle(R.string.playlist_update_info)
|
||||||
.setView(dialogView)
|
.setView(dialogView)
|
||||||
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.common_ok, (dialog, which) -> new LoadingTask<Void>(context, false) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
protected Void doInBackground() throws Throwable {
|
||||||
new LoadingTask<Void>(context, false) {
|
String name = nameBox.getText().toString();
|
||||||
@Override
|
String comment = commentBox.getText().toString();
|
||||||
protected Void doInBackground() throws Throwable {
|
boolean isPublic = publicBox.isChecked();
|
||||||
String name = nameBox.getText().toString();
|
|
||||||
String comment = commentBox.getText().toString();
|
|
||||||
boolean isPublic = publicBox.isChecked();
|
|
||||||
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null);
|
musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null);
|
||||||
|
|
||||||
playlist.setName(name);
|
playlist.setName(name);
|
||||||
playlist.setComment(comment);
|
playlist.setComment(comment);
|
||||||
playlist.setPublic(isPublic);
|
playlist.setPublic(isPublic);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done(Void result) {
|
||||||
|
Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void error(Throwable error) {
|
||||||
|
String msg;
|
||||||
|
if (error instanceof OfflineException) {
|
||||||
|
msg = getErrorMessage(error);
|
||||||
|
} else {
|
||||||
|
msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
Util.toast(context, msg, false);
|
||||||
protected void done(Void result) {
|
}
|
||||||
Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
}.execute())
|
||||||
}
|
.setNegativeButton(R.string.common_cancel, null)
|
||||||
|
.show();
|
||||||
@Override
|
|
||||||
protected void error(Throwable error) {
|
|
||||||
String msg;
|
|
||||||
if (error instanceof OfflineException) {
|
|
||||||
msg = getErrorMessage(error);
|
|
||||||
} else {
|
|
||||||
msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.toast(context, msg, false);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.common_cancel, null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncPlaylist(Playlist playlist) {
|
|
||||||
SyncUtil.addSyncedPlaylist(context, playlist.getId());
|
|
||||||
downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopSyncPlaylist(final Playlist playlist) {
|
|
||||||
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
|
||||||
|
|
||||||
new LoadingTask<Void>(context, false) {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
// Unpin all of the songs in playlist
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
|
||||||
MusicDirectory root = musicService.getPlaylist(true, playlist.getId(), playlist.getName(), context, this);
|
|
||||||
for(MusicDirectory.Entry entry: root.getChildren()) {
|
|
||||||
DownloadFile file = new DownloadFile(context, entry, false);
|
|
||||||
file.unpin();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,27 +15,16 @@
|
|||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.app.SearchManager;
|
|
||||||
import android.app.SearchableInfo;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.SearchView;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
@ -45,23 +34,27 @@ import net.nullsum.audinaut.util.ProgressListener;
|
|||||||
import net.nullsum.audinaut.util.TabBackgroundTask;
|
import net.nullsum.audinaut.util.TabBackgroundTask;
|
||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class SelectRecyclerFragment<T> extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<T> {
|
public abstract class SelectRecyclerFragment<T> extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<T> {
|
||||||
private static final String TAG = SelectRecyclerFragment.class.getSimpleName();
|
private static final String TAG = SelectRecyclerFragment.class.getSimpleName();
|
||||||
protected RecyclerView recyclerView;
|
RecyclerView recyclerView;
|
||||||
protected FastScroller fastScroller;
|
SectionAdapter<T> adapter;
|
||||||
protected SectionAdapter<T> adapter;
|
List<T> objects;
|
||||||
protected UpdateTask currentTask;
|
boolean serialize = true;
|
||||||
protected List<T> objects;
|
boolean largeAlbums = false;
|
||||||
protected boolean serialize = true;
|
boolean pullToRefresh = true;
|
||||||
protected boolean largeAlbums = false;
|
boolean backgroundUpdate = true;
|
||||||
protected boolean pullToRefresh = true;
|
private FastScroller fastScroller;
|
||||||
protected boolean backgroundUpdate = true;
|
private UpdateTask currentTask;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
if(bundle != null && serialize) {
|
if (bundle != null && serialize) {
|
||||||
objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +62,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
if(serialize) {
|
if (serialize) {
|
||||||
outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects);
|
outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,20 +71,20 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
||||||
|
|
||||||
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
refreshLayout = rootView.findViewById(R.id.refresh_layout);
|
||||||
refreshLayout.setOnRefreshListener(this);
|
refreshLayout.setOnRefreshListener(this);
|
||||||
|
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
recyclerView = rootView.findViewById(R.id.fragment_recycler);
|
||||||
fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller);
|
fastScroller = rootView.findViewById(R.id.fragment_fast_scroller);
|
||||||
setupLayoutManager();
|
setupLayoutManager();
|
||||||
|
|
||||||
if(pullToRefresh) {
|
if (pullToRefresh) {
|
||||||
setupScrollList(recyclerView);
|
setupScrollList(recyclerView);
|
||||||
} else {
|
} else {
|
||||||
refreshLayout.setEnabled(false);
|
refreshLayout.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(objects == null) {
|
if (objects == null) {
|
||||||
refresh(false);
|
refresh(false);
|
||||||
} else {
|
} else {
|
||||||
recyclerView.setAdapter(adapter = getAdapter(objects));
|
recyclerView.setAdapter(adapter = getAdapter(objects));
|
||||||
@ -102,7 +95,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(!primaryFragment) {
|
if (!primaryFragment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,44 +103,39 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
onFinishSetupOptionsMenu(menu);
|
onFinishSetupOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
||||||
boolean update = this.isOnlyVisible != isOnlyVisible;
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
||||||
super.setIsOnlyVisible(isOnlyVisible);
|
super.setIsOnlyVisible(isOnlyVisible);
|
||||||
if(update && adapter != null) {
|
if (update && adapter != null) {
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if (layoutManager instanceof GridLayoutManager) {
|
||||||
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void refresh(final boolean refresh) {
|
void refresh(final boolean refresh) {
|
||||||
int titleRes = getTitleResource();
|
int titleRes = getTitleResource();
|
||||||
if(titleRes != 0) {
|
if (titleRes != 0) {
|
||||||
setTitle(getTitleResource());
|
setTitle(getTitleResource());
|
||||||
}
|
}
|
||||||
if(backgroundUpdate) {
|
if (backgroundUpdate) {
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel current running task before starting another one
|
// Cancel current running task before starting another one
|
||||||
if(currentTask != null) {
|
if (currentTask != null) {
|
||||||
currentTask.cancel();
|
currentTask.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTask = new UpdateTask(this, refresh);
|
currentTask = new UpdateTask(this, refresh);
|
||||||
|
|
||||||
if(backgroundUpdate) {
|
if (backgroundUpdate) {
|
||||||
currentTask.execute();
|
currentTask.execute();
|
||||||
} else {
|
} else {
|
||||||
objects = new ArrayList<T>();
|
objects = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objects = getObjects(null, refresh, null);
|
objects = getObjects(null, refresh, null);
|
||||||
@ -167,17 +155,20 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
setupLayoutManager(recyclerView, largeAlbums);
|
setupLayoutManager(recyclerView, largeAlbums);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int getOptionsMenu();
|
protected abstract int getOptionsMenu();
|
||||||
public abstract SectionAdapter<T> getAdapter(List<T> objs);
|
|
||||||
public abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception;
|
|
||||||
public abstract int getTitleResource();
|
|
||||||
|
|
||||||
public void onFinishRefresh() {
|
protected abstract SectionAdapter<T> getAdapter(List<T> objs);
|
||||||
|
|
||||||
|
protected abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception;
|
||||||
|
|
||||||
|
protected abstract int getTitleResource();
|
||||||
|
|
||||||
|
void onFinishRefresh() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdateTask extends TabBackgroundTask<List<T>> {
|
private class UpdateTask extends TabBackgroundTask<List<T>> {
|
||||||
private boolean refresh;
|
private final boolean refresh;
|
||||||
|
|
||||||
public UpdateTask(SubsonicFragment fragment, boolean refresh) {
|
public UpdateTask(SubsonicFragment fragment, boolean refresh) {
|
||||||
super(fragment);
|
super(fragment);
|
||||||
@ -188,7 +179,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
public List<T> doInBackground() throws Exception {
|
public List<T> doInBackground() throws Exception {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
|
|
||||||
objects = new ArrayList<T>();
|
objects = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objects = getObjects(musicService, refresh, this);
|
objects = getObjects(musicService, refresh, this);
|
||||||
@ -203,7 +194,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
|
|||||||
public void done(List<T> result) {
|
public void done(List<T> result) {
|
||||||
if (result != null && !result.isEmpty()) {
|
if (result != null && !result.isEmpty()) {
|
||||||
recyclerView.setAdapter(adapter = getAdapter(result));
|
recyclerView.setAdapter(adapter = getAdapter(result));
|
||||||
if(!fastScroller.isAttached()) {
|
if (!fastScroller.isAttached()) {
|
||||||
fastScroller.attachRecyclerView(recyclerView);
|
fastScroller.attachRecyclerView(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,6 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.adapter.BasicListAdapter;
|
import net.nullsum.audinaut.adapter.BasicListAdapter;
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
@ -31,6 +28,9 @@ import net.nullsum.audinaut.util.Constants;
|
|||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
||||||
|
|
||||||
public SelectYearFragment() {
|
public SelectYearFragment() {
|
||||||
@ -53,7 +53,7 @@ public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
|||||||
@Override
|
@Override
|
||||||
public List<String> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<String> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<String> decades = new ArrayList<>();
|
List<String> decades = new ArrayList<>();
|
||||||
for(int i = 2010; i >= 1800; i -= 10) {
|
for (int i = 2010; i >= 1800; i -= 10) {
|
||||||
decades.add(String.valueOf(i));
|
decades.add(String.valueOf(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,8 @@ public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<String> updateView, String item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<String> updateView, String item) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<String> updateView, String item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<String> updateView, String item) {
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
|
import android.app.backup.BackupManager;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -31,21 +30,11 @@ import android.preference.PreferenceCategory;
|
|||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
||||||
@ -59,10 +48,16 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
import net.nullsum.audinaut.view.CacheLocationPreference;
|
import net.nullsum.audinaut.view.CacheLocationPreference;
|
||||||
import net.nullsum.audinaut.view.ErrorDialog;
|
import net.nullsum.audinaut.view.ErrorDialog;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceCompatFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class SettingsFragment extends PreferenceCompatFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private final static String TAG = SettingsFragment.class.getSimpleName();
|
private final static String TAG = SettingsFragment.class.getSimpleName();
|
||||||
|
|
||||||
private final Map<String, ServerSettings> serverSettings = new LinkedHashMap<String, ServerSettings>();
|
private final Map<String, ServerSettings> serverSettings = new LinkedHashMap<>();
|
||||||
private boolean testingConnection;
|
private boolean testingConnection;
|
||||||
private ListPreference theme;
|
private ListPreference theme;
|
||||||
private ListPreference maxBitrateWifi;
|
private ListPreference maxBitrateWifi;
|
||||||
@ -74,7 +69,6 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
private ListPreference keepPlayedCount;
|
private ListPreference keepPlayedCount;
|
||||||
private ListPreference tempLoss;
|
private ListPreference tempLoss;
|
||||||
private ListPreference pauseDisconnect;
|
private ListPreference pauseDisconnect;
|
||||||
private Preference addServerPreference;
|
|
||||||
private PreferenceCategory serversCategory;
|
private PreferenceCategory serversCategory;
|
||||||
private ListPreference songPressAction;
|
private ListPreference songPressAction;
|
||||||
private ListPreference syncInterval;
|
private ListPreference syncInterval;
|
||||||
@ -122,17 +116,17 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
int xml = 0;
|
int xml = 0;
|
||||||
if("appearance".equals(name)) {
|
if ("appearance".equals(name)) {
|
||||||
xml = R.xml.settings_appearance;
|
xml = R.xml.settings_appearance;
|
||||||
} else if("cache".equals(name)) {
|
} else if ("cache".equals(name)) {
|
||||||
xml = R.xml.settings_cache;
|
xml = R.xml.settings_cache;
|
||||||
} else if("playback".equals(name)) {
|
} else if ("playback".equals(name)) {
|
||||||
xml = R.xml.settings_playback;
|
xml = R.xml.settings_playback;
|
||||||
} else if("servers".equals(name)) {
|
} else if ("servers".equals(name)) {
|
||||||
xml = R.xml.settings_servers;
|
xml = R.xml.settings_servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xml != 0) {
|
if (xml != 0) {
|
||||||
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, xml);
|
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, xml);
|
||||||
newFragment.setArguments(args);
|
newFragment.setArguments(args);
|
||||||
replaceFragment(newFragment);
|
replaceFragment(newFragment);
|
||||||
@ -142,7 +136,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
// Random error I have no idea how to reproduce
|
// Random error I have no idea how to reproduce
|
||||||
if(sharedPreferences == null) {
|
if (sharedPreferences == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,25 +144,22 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
|
|
||||||
if (Constants.PREFERENCES_KEY_HIDE_MEDIA.equals(key)) {
|
if (Constants.PREFERENCES_KEY_HIDE_MEDIA.equals(key)) {
|
||||||
setHideMedia(sharedPreferences.getBoolean(key, true));
|
setHideMedia(sharedPreferences.getBoolean(key, true));
|
||||||
}
|
} else if (Constants.PREFERENCES_KEY_MEDIA_BUTTONS.equals(key)) {
|
||||||
else if (Constants.PREFERENCES_KEY_MEDIA_BUTTONS.equals(key)) {
|
|
||||||
setMediaButtonsEnabled(sharedPreferences.getBoolean(key, true));
|
setMediaButtonsEnabled(sharedPreferences.getBoolean(key, true));
|
||||||
}
|
} else if (Constants.PREFERENCES_KEY_CACHE_LOCATION.equals(key)) {
|
||||||
else if (Constants.PREFERENCES_KEY_CACHE_LOCATION.equals(key)) {
|
|
||||||
setCacheLocation(sharedPreferences.getString(key, ""));
|
setCacheLocation(sharedPreferences.getString(key, ""));
|
||||||
}
|
} else if (Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) {
|
||||||
else if(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) {
|
|
||||||
SyncUtil.removeMostRecentSyncFiles(context);
|
SyncUtil.removeMostRecentSyncFiles(context);
|
||||||
} else if(Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(key)) {
|
} else if (Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(key)) {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
if(downloadService != null) {
|
if (downloadService != null) {
|
||||||
downloadService.reapplyVolume();
|
downloadService.reapplyVolume();
|
||||||
}
|
}
|
||||||
} else if(Constants.PREFERENCES_KEY_START_ON_HEADPHONES.equals(key)) {
|
} else if (Constants.PREFERENCES_KEY_START_ON_HEADPHONES.equals(key)) {
|
||||||
Intent serviceIntent = new Intent();
|
Intent serviceIntent = new Intent();
|
||||||
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
||||||
|
|
||||||
if(sharedPreferences.getBoolean(key, false)) {
|
if (sharedPreferences.getBoolean(key, false)) {
|
||||||
context.startService(serviceIntent);
|
context.startService(serviceIntent);
|
||||||
} else {
|
} else {
|
||||||
context.stopService(serviceIntent);
|
context.stopService(serviceIntent);
|
||||||
@ -199,7 +190,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
tempLoss = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_TEMP_LOSS);
|
tempLoss = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_TEMP_LOSS);
|
||||||
pauseDisconnect = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT);
|
pauseDisconnect = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT);
|
||||||
serversCategory = (PreferenceCategory) this.findPreference(Constants.PREFERENCES_KEY_SERVER_KEY);
|
serversCategory = (PreferenceCategory) this.findPreference(Constants.PREFERENCES_KEY_SERVER_KEY);
|
||||||
addServerPreference = this.findPreference(Constants.PREFERENCES_KEY_SERVER_ADD);
|
Preference addServerPreference = this.findPreference(Constants.PREFERENCES_KEY_SERVER_ADD);
|
||||||
songPressAction = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION);
|
songPressAction = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION);
|
||||||
syncInterval = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_INTERVAL);
|
syncInterval = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_INTERVAL);
|
||||||
syncEnabled = (CheckBoxPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED);
|
syncEnabled = (CheckBoxPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED);
|
||||||
@ -215,86 +206,69 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
settings = Util.getPreferences(context);
|
settings = Util.getPreferences(context);
|
||||||
serverCount = settings.getInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1);
|
serverCount = settings.getInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1);
|
||||||
|
|
||||||
if(cacheSize != null) {
|
if (cacheSize != null) {
|
||||||
this.findPreference("clearCache").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
this.findPreference("clearCache").setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
Util.confirmDialog(context, (dialog, which) -> new LoadingTask<Void>(context, false) {
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
@Override
|
||||||
Util.confirmDialog(context, R.string.common_delete, R.string.common_confirm_message_cache, new DialogInterface.OnClickListener() {
|
protected Void doInBackground() throws Throwable {
|
||||||
@Override
|
FileUtil.deleteMusicDirectory(context);
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
FileUtil.deleteSerializedCache(context);
|
||||||
new LoadingTask<Void>(context, false) {
|
FileUtil.deleteArtworkCache(context);
|
||||||
@Override
|
return null;
|
||||||
protected Void doInBackground() throws Throwable {
|
}
|
||||||
FileUtil.deleteMusicDirectory(context);
|
|
||||||
FileUtil.deleteSerializedCache(context);
|
|
||||||
FileUtil.deleteArtworkCache(context);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
Util.toast(context, R.string.settings_cache_clear_complete);
|
Util.toast(context, R.string.settings_cache_clear_complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
Util.toast(context, getErrorMessage(error), false);
|
Util.toast(context, getErrorMessage(error), false);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute());
|
||||||
}
|
return false;
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(syncEnabled != null) {
|
if (syncEnabled != null) {
|
||||||
this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED).setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
@Override
|
Boolean syncEnabled = (Boolean) newValue;
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
Boolean syncEnabled = (Boolean) newValue;
|
|
||||||
|
|
||||||
Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
|
Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
|
||||||
ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled);
|
ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
syncInterval.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
syncInterval.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
@Override
|
Integer syncInterval = Integer.parseInt(((String) newValue));
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
Integer syncInterval = Integer.parseInt(((String) newValue));
|
|
||||||
|
|
||||||
Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
|
Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
|
||||||
ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval);
|
ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serversCategory != null) {
|
if (serversCategory != null) {
|
||||||
addServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
addServerPreference.setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
serverCount++;
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
int instance = serverCount;
|
||||||
serverCount++;
|
serversCategory.addPreference(addServer(serverCount));
|
||||||
int instance = serverCount;
|
|
||||||
serversCategory.addPreference(addServer(serverCount));
|
|
||||||
|
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount);
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount);
|
||||||
// Reset set folder ID
|
// Reset set folder ID
|
||||||
editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null);
|
editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null);
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + instance, "http://yourhost");
|
editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + instance, "http://yourhost");
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, getResources().getString(R.string.settings_server_unused));
|
editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, getResources().getString(R.string.settings_server_unused));
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
ServerSettings ss = new ServerSettings(instance);
|
ServerSettings ss = new ServerSettings(instance);
|
||||||
serverSettings.put(String.valueOf(instance), ss);
|
serverSettings.put(String.valueOf(instance), ss);
|
||||||
ss.update();
|
ss.update();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
serversCategory.setOrderingAsAdded(false);
|
serversCategory.setOrderingAsAdded(false);
|
||||||
@ -311,18 +285,8 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleBackup() {
|
private void scheduleBackup() {
|
||||||
try {
|
BackupManager backupManager = new BackupManager(context);
|
||||||
Class managerClass = Class.forName("android.app.backup.BackupManager");
|
backupManager.dataChanged();
|
||||||
Constructor managerConstructor = managerClass.getConstructor(Context.class);
|
|
||||||
Object manager = managerConstructor.newInstance(context);
|
|
||||||
Method m = managerClass.getMethod("dataChanged");
|
|
||||||
m.invoke(manager);
|
|
||||||
} catch(ClassNotFoundException e) {
|
|
||||||
Log.e(TAG, "No backup manager found");
|
|
||||||
} catch(Throwable t) {
|
|
||||||
Log.e(TAG, "Scheduling backup failed " + t);
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
@ -330,11 +294,11 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(theme != null) {
|
if (theme != null) {
|
||||||
theme.setSummary(theme.getEntry());
|
theme.setSummary(theme.getEntry());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cacheSize != null) {
|
if (cacheSize != null) {
|
||||||
maxBitrateWifi.setSummary(maxBitrateWifi.getEntry());
|
maxBitrateWifi.setSummary(maxBitrateWifi.getEntry());
|
||||||
maxBitrateMobile.setSummary(maxBitrateMobile.getEntry());
|
maxBitrateMobile.setSummary(maxBitrateMobile.getEntry());
|
||||||
networkTimeout.setSummary(networkTimeout.getEntry());
|
networkTimeout.setSummary(networkTimeout.getEntry());
|
||||||
@ -343,24 +307,24 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
preloadCountMobile.setSummary(preloadCountMobile.getEntry());
|
preloadCountMobile.setSummary(preloadCountMobile.getEntry());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(megabyteFromat == null) {
|
if (megabyteFromat == null) {
|
||||||
megabyteFromat = new DecimalFormat(getResources().getString(R.string.util_bytes_format_megabyte));
|
megabyteFromat = new DecimalFormat(getResources().getString(R.string.util_bytes_format_megabyte));
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheSize.setSummary(megabyteFromat.format((double) Integer.parseInt(cacheSize.getText())).replace(".00", ""));
|
cacheSize.setSummary(megabyteFromat.format((double) Integer.parseInt(cacheSize.getText())).replace(".00", ""));
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to format cache size", e);
|
Log.e(TAG, "Failed to format cache size", e);
|
||||||
cacheSize.setSummary(cacheSize.getText());
|
cacheSize.setSummary(cacheSize.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(keepPlayedCount != null) {
|
if (keepPlayedCount != null) {
|
||||||
keepPlayedCount.setSummary(keepPlayedCount.getEntry());
|
keepPlayedCount.setSummary(keepPlayedCount.getEntry());
|
||||||
tempLoss.setSummary(tempLoss.getEntry());
|
tempLoss.setSummary(tempLoss.getEntry());
|
||||||
pauseDisconnect.setSummary(pauseDisconnect.getEntry());
|
pauseDisconnect.setSummary(pauseDisconnect.getEntry());
|
||||||
songPressAction.setSummary(songPressAction.getEntry());
|
songPressAction.setSummary(songPressAction.getEntry());
|
||||||
|
|
||||||
if(replayGain.isChecked()) {
|
if (replayGain.isChecked()) {
|
||||||
replayGainType.setEnabled(true);
|
replayGainType.setEnabled(true);
|
||||||
replayGainBump.setEnabled(true);
|
replayGainBump.setEnabled(true);
|
||||||
replayGainUntagged.setEnabled(true);
|
replayGainUntagged.setEnabled(true);
|
||||||
@ -372,18 +336,18 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
replayGainType.setSummary(replayGainType.getEntry());
|
replayGainType.setSummary(replayGainType.getEntry());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(syncEnabled != null) {
|
if (syncEnabled != null) {
|
||||||
syncInterval.setSummary(syncInterval.getEntry());
|
syncInterval.setSummary(syncInterval.getEntry());
|
||||||
|
|
||||||
if(syncEnabled.isChecked()) {
|
if (syncEnabled.isChecked()) {
|
||||||
if(!syncInterval.isEnabled()) {
|
if (!syncInterval.isEnabled()) {
|
||||||
syncInterval.setEnabled(true);
|
syncInterval.setEnabled(true);
|
||||||
syncWifi.setEnabled(true);
|
syncWifi.setEnabled(true);
|
||||||
syncNotification.setEnabled(true);
|
syncNotification.setEnabled(true);
|
||||||
syncMostRecent.setEnabled(true);
|
syncMostRecent.setEnabled(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(syncInterval.isEnabled()) {
|
if (syncInterval.isEnabled()) {
|
||||||
syncInterval.setEnabled(false);
|
syncInterval.setEnabled(false);
|
||||||
syncWifi.setEnabled(false);
|
syncWifi.setEnabled(false);
|
||||||
syncNotification.setEnabled(false);
|
syncNotification.setEnabled(false);
|
||||||
@ -396,9 +360,10 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
ss.update();
|
ss.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void checkForRemoved() {
|
|
||||||
|
private void checkForRemoved() {
|
||||||
for (ServerSettings ss : serverSettings.values()) {
|
for (ServerSettings ss : serverSettings.values()) {
|
||||||
if(!ss.update()) {
|
if (!ss.update()) {
|
||||||
serversCategory.removePreference(ss.getScreen());
|
serversCategory.removePreference(ss.getScreen());
|
||||||
serverCount--;
|
serverCount--;
|
||||||
}
|
}
|
||||||
@ -410,18 +375,15 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
screen.setKey(Constants.PREFERENCES_KEY_SERVER_KEY + instance);
|
screen.setKey(Constants.PREFERENCES_KEY_SERVER_KEY + instance);
|
||||||
screen.setOrder(instance);
|
screen.setOrder(instance);
|
||||||
|
|
||||||
screen.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
screen.setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
SettingsFragment newFragment = new SettingsFragment();
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
SettingsFragment newFragment = new SettingsFragment();
|
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance);
|
args.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance);
|
||||||
newFragment.setArguments(args);
|
newFragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(newFragment);
|
replaceFragment(newFragment);
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
@ -466,12 +428,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
|
|
||||||
Button defaultButton = new Button(getContext());
|
Button defaultButton = new Button(getContext());
|
||||||
defaultButton.setText(internalSSIDDisplay);
|
defaultButton.setText(internalSSIDDisplay);
|
||||||
defaultButton.setOnClickListener(new View.OnClickListener() {
|
defaultButton.setOnClickListener(v -> editText.setText(internalSSID));
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
editText.setText(internalSSID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
root.addView(defaultButton);
|
root.addView(defaultButton);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -502,12 +459,9 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER);
|
serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER);
|
||||||
serverOpenBrowser.setPersistent(false);
|
serverOpenBrowser.setPersistent(false);
|
||||||
serverOpenBrowser.setTitle(R.string.settings_server_open_browser);
|
serverOpenBrowser.setTitle(R.string.settings_server_open_browser);
|
||||||
serverOpenBrowser.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
serverOpenBrowser.setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
openInBrowser(instance);
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
return true;
|
||||||
openInBrowser(instance);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Preference serverRemoveServerPreference = new Preference(context);
|
Preference serverRemoveServerPreference = new Preference(context);
|
||||||
@ -515,53 +469,44 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
serverRemoveServerPreference.setPersistent(false);
|
serverRemoveServerPreference.setPersistent(false);
|
||||||
serverRemoveServerPreference.setTitle(R.string.settings_servers_remove);
|
serverRemoveServerPreference.setTitle(R.string.settings_servers_remove);
|
||||||
|
|
||||||
serverRemoveServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
serverRemoveServerPreference.setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
Util.confirmDialog(context, R.string.common_delete, screen.getTitle().toString(), (dialog, which) -> {
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
// Reset values to null so when we ask for them again they are new
|
||||||
Util.confirmDialog(context, R.string.common_delete, screen.getTitle().toString(), new DialogInterface.OnClickListener() {
|
serverNamePreference.setText(null);
|
||||||
@Override
|
serverUrlPreference.setText(null);
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
serverUsernamePreference.setText(null);
|
||||||
// Reset values to null so when we ask for them again they are new
|
serverPasswordPreference.setText(null);
|
||||||
serverNamePreference.setText(null);
|
|
||||||
serverUrlPreference.setText(null);
|
|
||||||
serverUsernamePreference.setText(null);
|
|
||||||
serverPasswordPreference.setText(null);
|
|
||||||
|
|
||||||
// Don't use Util.getActiveServer since it is 0 if offline
|
// Don't use Util.getActiveServer since it is 0 if offline
|
||||||
int activeServer = Util.getPreferences(context).getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
|
int activeServer = Util.getPreferences(context).getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
|
||||||
for (int i = instance; i <= serverCount; i++) {
|
for (int i = instance; i <= serverCount; i++) {
|
||||||
Util.removeInstanceName(context, i, activeServer);
|
Util.removeInstanceName(context, i, activeServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverCount--;
|
serverCount--;
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount);
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
removeCurrent();
|
removeCurrent();
|
||||||
|
|
||||||
SubsonicFragment parentFragment = context.getCurrentFragment();
|
SubsonicFragment parentFragment = context.getCurrentFragment();
|
||||||
if(parentFragment instanceof SettingsFragment) {
|
if (parentFragment instanceof SettingsFragment) {
|
||||||
SettingsFragment serverSelectionFragment = (SettingsFragment) parentFragment;
|
SettingsFragment serverSelectionFragment = (SettingsFragment) parentFragment;
|
||||||
serverSelectionFragment.checkForRemoved();
|
serverSelectionFragment.checkForRemoved();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Preference serverTestConnectionPreference = new Preference(context);
|
Preference serverTestConnectionPreference = new Preference(context);
|
||||||
serverTestConnectionPreference.setKey(Constants.PREFERENCES_KEY_TEST_CONNECTION + instance);
|
serverTestConnectionPreference.setKey(Constants.PREFERENCES_KEY_TEST_CONNECTION + instance);
|
||||||
serverTestConnectionPreference.setPersistent(false);
|
serverTestConnectionPreference.setPersistent(false);
|
||||||
serverTestConnectionPreference.setTitle(R.string.settings_test_connection_title);
|
serverTestConnectionPreference.setTitle(R.string.settings_test_connection_title);
|
||||||
serverTestConnectionPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
serverTestConnectionPreference.setOnPreferenceClickListener(preference -> {
|
||||||
@Override
|
testConnection(instance);
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
return false;
|
||||||
testConnection(instance);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
screen.addPreference(serverNamePreference);
|
screen.addPreference(serverNamePreference);
|
||||||
@ -585,22 +530,22 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
if (!nomediaDir.createNewFile()) {
|
if (!nomediaDir.createNewFile()) {
|
||||||
Log.w(TAG, "Failed to create " + nomediaDir);
|
Log.w(TAG, "Failed to create " + nomediaDir);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to create " + nomediaDir, e);
|
Log.w(TAG, "Failed to create " + nomediaDir, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(!musicNoMedia.createNewFile()) {
|
if (!musicNoMedia.createNewFile()) {
|
||||||
Log.w(TAG, "Failed to create " + musicNoMedia);
|
Log.w(TAG, "Failed to create " + musicNoMedia);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to create " + musicNoMedia, e);
|
Log.w(TAG, "Failed to create " + musicNoMedia, e);
|
||||||
}
|
}
|
||||||
} else if (!hide && nomediaDir.exists()) {
|
} else if (!hide && nomediaDir.exists()) {
|
||||||
if (!nomediaDir.delete()) {
|
if (!nomediaDir.delete()) {
|
||||||
Log.w(TAG, "Failed to delete " + nomediaDir);
|
Log.w(TAG, "Failed to delete " + nomediaDir);
|
||||||
}
|
}
|
||||||
if(!musicNoMedia.delete()) {
|
if (!musicNoMedia.delete()) {
|
||||||
Log.w(TAG, "Failed to delete " + musicNoMedia);
|
Log.w(TAG, "Failed to delete " + musicNoMedia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -628,7 +573,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, defaultPath);
|
editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, defaultPath);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
if(cacheLocation != null) {
|
if (cacheLocation != null) {
|
||||||
cacheLocation.setSummary(defaultPath);
|
cacheLocation.setSummary(defaultPath);
|
||||||
cacheLocation.setText(defaultPath);
|
cacheLocation.setText(defaultPath);
|
||||||
}
|
}
|
||||||
@ -646,7 +591,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground() throws Throwable {
|
protected Boolean doInBackground() throws Throwable {
|
||||||
updateProgress(R.string.settings_testing_connection);
|
updateProgress();
|
||||||
|
|
||||||
previousInstance = Util.getActiveServer(context);
|
previousInstance = Util.getActiveServer(context);
|
||||||
testingConnection = true;
|
testingConnection = true;
|
||||||
@ -685,8 +630,8 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
private void openInBrowser(final int instance) {
|
private void openInBrowser(final int instance) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String url = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
|
String url = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
|
||||||
if(url == null) {
|
if (url == null) {
|
||||||
new ErrorDialog(context, R.string.settings_invalid_url, false);
|
new ErrorDialog(context, R.string.settings_invalid_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Uri uriServer = Uri.parse(url);
|
Uri uriServer = Uri.parse(url);
|
||||||
@ -696,13 +641,13 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ServerSettings {
|
private class ServerSettings {
|
||||||
private int instance;
|
private final int instance;
|
||||||
private EditTextPreference serverName;
|
private final EditTextPreference serverName;
|
||||||
private EditTextPreference serverUrl;
|
private final EditTextPreference serverUrl;
|
||||||
private EditTextPreference serverLocalNetworkSSID;
|
private final EditTextPreference serverLocalNetworkSSID;
|
||||||
private EditTextPreference serverInternalUrl;
|
private final EditTextPreference serverInternalUrl;
|
||||||
private EditTextPreference username;
|
private final EditTextPreference username;
|
||||||
private PreferenceScreen screen;
|
private final PreferenceScreen screen;
|
||||||
|
|
||||||
private ServerSettings(int instance) {
|
private ServerSettings(int instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
@ -713,55 +658,46 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
serverInternalUrl = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance);
|
serverInternalUrl = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance);
|
||||||
username = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_USERNAME + instance);
|
username = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_USERNAME + instance);
|
||||||
|
|
||||||
if(serverName != null) {
|
if (serverName != null) {
|
||||||
serverUrl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
serverUrl.setOnPreferenceChangeListener((preference, value) -> {
|
||||||
@Override
|
try {
|
||||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
String url = (String) value;
|
||||||
try {
|
new URL(url);
|
||||||
String url = (String) value;
|
if (url.contains(" ") || url.contains("@") || url.contains("_")) {
|
||||||
new URL(url);
|
throw new Exception();
|
||||||
if (url.contains(" ") || url.contains("@") || url.contains("_")) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
} catch (Exception x) {
|
|
||||||
new ErrorDialog(context, R.string.settings_invalid_url, false);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
} catch (Exception x) {
|
||||||
|
new ErrorDialog(context, R.string.settings_invalid_url);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
serverInternalUrl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
serverInternalUrl.setOnPreferenceChangeListener((preference, value) -> {
|
||||||
@Override
|
try {
|
||||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
String url = (String) value;
|
||||||
try {
|
// Allow blank internal IP address
|
||||||
String url = (String) value;
|
if ("".equals(url) || url == null) {
|
||||||
// Allow blank internal IP address
|
return true;
|
||||||
if ("".equals(url) || url == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
new URL(url);
|
|
||||||
if (url.contains(" ") || url.contains("@") || url.contains("_")) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
} catch (Exception x) {
|
|
||||||
new ErrorDialog(context, R.string.settings_invalid_url, false);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
new URL(url);
|
||||||
|
if (url.contains(" ") || url.contains("@") || url.contains("_")) {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
new ErrorDialog(context, R.string.settings_invalid_url);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
username.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
username.setOnPreferenceChangeListener((preference, value) -> {
|
||||||
@Override
|
String username = (String) value;
|
||||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
if (username == null || !username.equals(username.trim())) {
|
||||||
String username = (String) value;
|
new ErrorDialog(context, R.string.settings_invalid_username);
|
||||||
if (username == null || !username.equals(username.trim())) {
|
return false;
|
||||||
new ErrorDialog(context, R.string.settings_invalid_username, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -773,7 +709,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||||||
public boolean update() {
|
public boolean update() {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
|
|
||||||
if(prefs.contains(Constants.PREFERENCES_KEY_SERVER_NAME + instance)) {
|
if (prefs.contains(Constants.PREFERENCES_KEY_SERVER_NAME + instance)) {
|
||||||
if (serverName != null) {
|
if (serverName != null) {
|
||||||
serverName.setSummary(serverName.getText());
|
serverName.setSummary(serverName.getText());
|
||||||
serverUrl.setSummary(serverUrl.getText());
|
serverUrl.setSummary(serverUrl.getText());
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,12 +24,6 @@ import android.content.ContentValues;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
@ -40,13 +34,16 @@ import net.nullsum.audinaut.service.MusicService;
|
|||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides search suggestions based on recent searches.
|
* Provides search suggestions based on recent searches.
|
||||||
*
|
*
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class AudinautSearchProvider extends ContentProvider {
|
public class AudinautSearchProvider extends ContentProvider {
|
||||||
private static final String TAG = AudinautSearchProvider.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/";
|
private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/";
|
||||||
private static final String[] COLUMNS = {"_id",
|
private static final String[] COLUMNS = {"_id",
|
||||||
@ -58,7 +55,7 @@ public class AudinautSearchProvider extends ContentProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
if(selectionArgs[0].isEmpty()) {
|
if (selectionArgs[0].isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,14 +84,14 @@ public class AudinautSearchProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add all results into one pot
|
// Add all results into one pot
|
||||||
List<Object> results = new ArrayList<Object>();
|
List<Object> results = new ArrayList<>();
|
||||||
results.addAll(searchResult.getArtists());
|
results.addAll(searchResult.getArtists());
|
||||||
results.addAll(searchResult.getAlbums());
|
results.addAll(searchResult.getAlbums());
|
||||||
results.addAll(searchResult.getSongs());
|
results.addAll(searchResult.getSongs());
|
||||||
|
|
||||||
// For each, calculate its string distance to the query
|
// For each, calculate its string distance to the query
|
||||||
for(Object obj: results) {
|
for (Object obj : results) {
|
||||||
if(obj instanceof Artist) {
|
if (obj instanceof Artist) {
|
||||||
Artist artist = (Artist) obj;
|
Artist artist = (Artist) obj;
|
||||||
artist.setCloseness(Util.getStringDistance(query, artist.getName()));
|
artist.setCloseness(Util.getStringDistance(query, artist.getName()));
|
||||||
} else {
|
} else {
|
||||||
@ -104,71 +101,64 @@ public class AudinautSearchProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort based on the closeness paramater
|
// Sort based on the closeness paramater
|
||||||
Collections.sort(results, new Comparator<Object>() {
|
Collections.sort(results, (lhs, rhs) -> {
|
||||||
@Override
|
// Get the closeness of the two objects
|
||||||
public int compare(Object lhs, Object rhs) {
|
int left, right;
|
||||||
// Get the closeness of the two objects
|
boolean leftArtist = lhs instanceof Artist;
|
||||||
int left, right;
|
boolean rightArtist = rhs instanceof Artist;
|
||||||
boolean leftArtist = lhs instanceof Artist;
|
if (leftArtist) {
|
||||||
boolean rightArtist = rhs instanceof Artist;
|
left = ((Artist) lhs).getCloseness();
|
||||||
if (leftArtist) {
|
} else {
|
||||||
left = ((Artist) lhs).getCloseness();
|
left = ((MusicDirectory.Entry) lhs).getCloseness();
|
||||||
} else {
|
}
|
||||||
left = ((MusicDirectory.Entry) lhs).getCloseness();
|
if (rightArtist) {
|
||||||
}
|
right = ((Artist) rhs).getCloseness();
|
||||||
if (rightArtist) {
|
} else {
|
||||||
right = ((Artist) rhs).getCloseness();
|
right = ((MusicDirectory.Entry) rhs).getCloseness();
|
||||||
} else {
|
}
|
||||||
right = ((MusicDirectory.Entry) rhs).getCloseness();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left == right) {
|
if (left == right) {
|
||||||
if(leftArtist && rightArtist) {
|
if (leftArtist && rightArtist) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if(leftArtist) {
|
} else if (leftArtist) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rightArtist) {
|
} else if (rightArtist) {
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else if (left > right) {
|
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else if (left > right) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Done sorting, add results to cursor
|
// Done sorting, add results to cursor
|
||||||
for(Object obj: results) {
|
for (Object obj : results) {
|
||||||
if(obj instanceof Artist) {
|
if (obj instanceof Artist) {
|
||||||
Artist artist = (Artist) obj;
|
Artist artist = (Artist) obj;
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist;
|
||||||
cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon});
|
cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon});
|
||||||
} else {
|
} else {
|
||||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
||||||
|
|
||||||
if(entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_album;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_album;
|
||||||
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon});
|
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon});
|
||||||
} else {
|
} else {
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_song;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_song;
|
||||||
String id;
|
String id;
|
||||||
if(Util.isTagBrowsing(getContext())) {
|
id = entry.getAlbumId();
|
||||||
id = entry.getAlbumId();
|
|
||||||
} else {
|
|
||||||
id = entry.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
String artistDisplay;
|
String artistDisplay;
|
||||||
if(entry.getArtist() == null) {
|
if (entry.getArtist() == null) {
|
||||||
if(entry.getAlbum() != null) {
|
if (entry.getAlbum() != null) {
|
||||||
artistDisplay = entry.getAlbumDisplay();
|
artistDisplay = entry.getAlbumDisplay();
|
||||||
} else {
|
} else {
|
||||||
artistDisplay = "";
|
artistDisplay = "";
|
||||||
}
|
}
|
||||||
} else if(entry.getAlbum() != null) {
|
} else if (entry.getAlbum() != null) {
|
||||||
artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay();
|
artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay();
|
||||||
} else {
|
} else {
|
||||||
artistDisplay = entry.getArtist();
|
artistDisplay = entry.getArtist();
|
||||||
|
@ -24,8 +24,8 @@ import android.appwidget.AppWidgetProvider;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Bitmap.Config;
|
import android.graphics.Bitmap.Config;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@ -38,6 +38,7 @@ import android.os.Environment;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.activity.SubsonicActivity;
|
import net.nullsum.audinaut.activity.SubsonicActivity;
|
||||||
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
||||||
@ -66,16 +67,16 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
private static AudinautWidget4x4 instance4x4;
|
private static AudinautWidget4x4 instance4x4;
|
||||||
|
|
||||||
public static synchronized void notifyInstances(Context context, DownloadService service, boolean playing) {
|
public static synchronized void notifyInstances(Context context, DownloadService service, boolean playing) {
|
||||||
if(instance4x1 == null) {
|
if (instance4x1 == null) {
|
||||||
instance4x1 = new AudinautWidget4x1();
|
instance4x1 = new AudinautWidget4x1();
|
||||||
}
|
}
|
||||||
if(instance4x2 == null) {
|
if (instance4x2 == null) {
|
||||||
instance4x2 = new AudinautWidget4x2();
|
instance4x2 = new AudinautWidget4x2();
|
||||||
}
|
}
|
||||||
if(instance4x3 == null) {
|
if (instance4x3 == null) {
|
||||||
instance4x3 = new AudinautWidget4x3();
|
instance4x3 = new AudinautWidget4x3();
|
||||||
}
|
}
|
||||||
if(instance4x4 == null) {
|
if (instance4x4 == null) {
|
||||||
instance4x4 = new AudinautWidget4x4();
|
instance4x4 = new AudinautWidget4x4();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,165 +86,6 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
instance4x4.notifyChange(context, service, playing);
|
instance4x4.notifyChange(context, service, playing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
|
||||||
defaultAppWidget(context, appWidgetIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnabled(Context context) {
|
|
||||||
notifyInstances(context, DownloadService.getInstance(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getLayout() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize given widgets to default state, where we launch Subsonic on default click
|
|
||||||
* and hide actions if service not running.
|
|
||||||
*/
|
|
||||||
private void defaultAppWidget(Context context, int[] appWidgetIds) {
|
|
||||||
final Resources res = context.getResources();
|
|
||||||
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
|
||||||
|
|
||||||
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
|
||||||
if(getLayout() == R.layout.appwidget4x2) {
|
|
||||||
views.setTextViewText(R.id.album, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
linkButtons(context, views, false);
|
|
||||||
performUpdate(context, null, appWidgetIds, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
|
|
||||||
// Update specific list of appWidgetIds if given, otherwise default to all
|
|
||||||
final AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
|
||||||
if (appWidgetIds != null) {
|
|
||||||
manager.updateAppWidget(appWidgetIds, views);
|
|
||||||
} else {
|
|
||||||
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a change notification coming over from {@link DownloadService}
|
|
||||||
*/
|
|
||||||
public void notifyChange(Context context, DownloadService service, boolean playing) {
|
|
||||||
if (hasInstances(context)) {
|
|
||||||
performUpdate(context, service, null, playing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check against {@link AppWidgetManager} if there are any instances of this widget.
|
|
||||||
*/
|
|
||||||
private boolean hasInstances(Context context) {
|
|
||||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
|
||||||
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
|
|
||||||
return (appWidgetIds.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update all active widget instances by pushing changes
|
|
||||||
*/
|
|
||||||
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing) {
|
|
||||||
final Resources res = context.getResources();
|
|
||||||
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
|
||||||
|
|
||||||
if(playing) {
|
|
||||||
views.setViewVisibility(R.id.widget_root, View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
// Hide widget
|
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
|
||||||
if(prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) {
|
|
||||||
views.setViewVisibility(R.id.widget_root, View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Entry from current playing DownloadFile
|
|
||||||
MusicDirectory.Entry currentPlaying = null;
|
|
||||||
if(service == null) {
|
|
||||||
// Deserialize from playling list to setup
|
|
||||||
try {
|
|
||||||
PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
|
||||||
if (state != null && state.currentPlayingIndex != -1) {
|
|
||||||
currentPlaying = state.songs.get(state.currentPlayingIndex);
|
|
||||||
}
|
|
||||||
} catch(Exception e) {
|
|
||||||
Log.e(TAG, "Failed to grab current playing", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
|
||||||
}
|
|
||||||
|
|
||||||
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
|
||||||
CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
|
||||||
CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
|
||||||
CharSequence errorState = null;
|
|
||||||
|
|
||||||
// Show error message?
|
|
||||||
String status = Environment.getExternalStorageState();
|
|
||||||
if (status.equals(Environment.MEDIA_SHARED) ||
|
|
||||||
status.equals(Environment.MEDIA_UNMOUNTED)) {
|
|
||||||
errorState = res.getText(R.string.widget_sdcard_busy);
|
|
||||||
} else if (status.equals(Environment.MEDIA_REMOVED)) {
|
|
||||||
errorState = res.getText(R.string.widget_sdcard_missing);
|
|
||||||
} else if (currentPlaying == null) {
|
|
||||||
errorState = res.getText(R.string.widget_initial_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorState != null) {
|
|
||||||
// Show error state to user
|
|
||||||
views.setTextViewText(R.id.title,null);
|
|
||||||
views.setTextViewText(R.id.artist, errorState);
|
|
||||||
views.setTextViewText(R.id.album, "");
|
|
||||||
if(getLayout() != R.layout.appwidget4x1) {
|
|
||||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No error, so show normal titles
|
|
||||||
views.setTextViewText(R.id.title, title);
|
|
||||||
views.setTextViewText(R.id.artist, artist);
|
|
||||||
if(getLayout() != R.layout.appwidget4x1) {
|
|
||||||
views.setTextViewText(R.id.album, album);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set correct drawable for pause state
|
|
||||||
if (playing) {
|
|
||||||
views.setImageViewResource(R.id.control_play, R.drawable.media_pause_dark);
|
|
||||||
} else {
|
|
||||||
views.setImageViewResource(R.id.control_play, R.drawable.media_start_dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the cover art
|
|
||||||
try {
|
|
||||||
boolean large = false;
|
|
||||||
if(getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) {
|
|
||||||
large = true;
|
|
||||||
}
|
|
||||||
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
|
||||||
Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large);
|
|
||||||
|
|
||||||
if (bitmap == null) {
|
|
||||||
// Set default cover art
|
|
||||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown);
|
|
||||||
} else {
|
|
||||||
bitmap = getRoundedCornerBitmap(bitmap);
|
|
||||||
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap);
|
|
||||||
}
|
|
||||||
} catch (Exception x) {
|
|
||||||
Log.e(TAG, "Failed to load cover art", x);
|
|
||||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link actions buttons to intents
|
|
||||||
linkButtons(context, views, currentPlaying != null);
|
|
||||||
|
|
||||||
pushUpdate(context, appWidgetIds, views);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Round the corners of a bitmap for the cover art image
|
* Round the corners of a bitmap for the cover art image
|
||||||
*/
|
*/
|
||||||
@ -270,12 +112,169 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||||
|
defaultAppWidget(context, appWidgetIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnabled(Context context) {
|
||||||
|
notifyInstances(context, DownloadService.getInstance(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLayout() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize given widgets to default state, where we launch Subsonic on default click
|
||||||
|
* and hide actions if service not running.
|
||||||
|
*/
|
||||||
|
private void defaultAppWidget(Context context, int[] appWidgetIds) {
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
||||||
|
|
||||||
|
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
||||||
|
if (getLayout() == R.layout.appwidget4x2) {
|
||||||
|
views.setTextViewText(R.id.album, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
linkButtons(context, views);
|
||||||
|
performUpdate(context, null, appWidgetIds, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
|
||||||
|
// Update specific list of appWidgetIds if given, otherwise default to all
|
||||||
|
final AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||||
|
if (appWidgetIds != null) {
|
||||||
|
manager.updateAppWidget(appWidgetIds, views);
|
||||||
|
} else {
|
||||||
|
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a change notification coming over from {@link DownloadService}
|
||||||
|
*/
|
||||||
|
void notifyChange(Context context, DownloadService service, boolean playing) {
|
||||||
|
if (hasInstances(context)) {
|
||||||
|
performUpdate(context, service, null, playing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check against {@link AppWidgetManager} if there are any instances of this widget.
|
||||||
|
*/
|
||||||
|
private boolean hasInstances(Context context) {
|
||||||
|
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||||
|
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
|
||||||
|
return (appWidgetIds.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update all active widget instances by pushing changes
|
||||||
|
*/
|
||||||
|
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing) {
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
||||||
|
|
||||||
|
if (playing) {
|
||||||
|
views.setViewVisibility(R.id.widget_root, View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
// Hide widget
|
||||||
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
|
if (prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) {
|
||||||
|
views.setViewVisibility(R.id.widget_root, View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Entry from current playing DownloadFile
|
||||||
|
MusicDirectory.Entry currentPlaying = null;
|
||||||
|
if (service == null) {
|
||||||
|
// Deserialize from playling list to setup
|
||||||
|
try {
|
||||||
|
PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
||||||
|
if (state != null && state.currentPlayingIndex != -1) {
|
||||||
|
currentPlaying = state.songs.get(state.currentPlayingIndex);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to grab current playing", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
||||||
|
}
|
||||||
|
|
||||||
|
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
||||||
|
CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
||||||
|
CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
||||||
|
CharSequence errorState = null;
|
||||||
|
|
||||||
|
// Show error message?
|
||||||
|
String status = Environment.getExternalStorageState();
|
||||||
|
if (status.equals(Environment.MEDIA_SHARED) ||
|
||||||
|
status.equals(Environment.MEDIA_UNMOUNTED)) {
|
||||||
|
errorState = res.getText(R.string.widget_sdcard_busy);
|
||||||
|
} else if (status.equals(Environment.MEDIA_REMOVED)) {
|
||||||
|
errorState = res.getText(R.string.widget_sdcard_missing);
|
||||||
|
} else if (currentPlaying == null) {
|
||||||
|
errorState = res.getText(R.string.widget_initial_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorState != null) {
|
||||||
|
// Show error state to user
|
||||||
|
views.setTextViewText(R.id.title, null);
|
||||||
|
views.setTextViewText(R.id.artist, errorState);
|
||||||
|
views.setTextViewText(R.id.album, "");
|
||||||
|
if (getLayout() != R.layout.appwidget4x1) {
|
||||||
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No error, so show normal titles
|
||||||
|
views.setTextViewText(R.id.title, title);
|
||||||
|
views.setTextViewText(R.id.artist, artist);
|
||||||
|
if (getLayout() != R.layout.appwidget4x1) {
|
||||||
|
views.setTextViewText(R.id.album, album);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set correct drawable for pause state
|
||||||
|
if (playing) {
|
||||||
|
views.setImageViewResource(R.id.control_play, R.drawable.media_pause_dark);
|
||||||
|
} else {
|
||||||
|
views.setImageViewResource(R.id.control_play, R.drawable.media_start_dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the cover art
|
||||||
|
try {
|
||||||
|
boolean large = false;
|
||||||
|
if (getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) {
|
||||||
|
large = true;
|
||||||
|
}
|
||||||
|
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
||||||
|
Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large);
|
||||||
|
|
||||||
|
if (bitmap == null) {
|
||||||
|
// Set default cover art
|
||||||
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown);
|
||||||
|
} else {
|
||||||
|
bitmap = getRoundedCornerBitmap(bitmap);
|
||||||
|
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
Log.e(TAG, "Failed to load cover art", x);
|
||||||
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link actions buttons to intents
|
||||||
|
linkButtons(context, views);
|
||||||
|
|
||||||
|
pushUpdate(context, appWidgetIds, views);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link up various button actions using {@link PendingIntent}.
|
* Link up various button actions using {@link PendingIntent}.
|
||||||
*
|
|
||||||
* @param playerActive @param playerActive True if player is active in background. Launch {@link net.nullsum.audinaut.activity.SubsonicFragmentActivity}.
|
|
||||||
*/
|
*/
|
||||||
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {
|
private void linkButtons(Context context, RemoteViews views) {
|
||||||
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
@ -4,11 +4,12 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
|
|
||||||
public class A2dpIntentReceiver extends BroadcastReceiver {
|
public class A2dpIntentReceiver extends BroadcastReceiver {
|
||||||
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
||||||
private String TAG = A2dpIntentReceiver.class.getSimpleName();
|
private final String TAG = A2dpIntentReceiver.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
@ -16,7 +17,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
|
|
||||||
if (downloadService != null){
|
if (downloadService != null) {
|
||||||
|
|
||||||
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver {
|
|||||||
avrcpIntent.putExtra("position", (long) downloadService.getPlayerPosition());
|
avrcpIntent.putExtra("position", (long) downloadService.getPlayerPosition());
|
||||||
avrcpIntent.putExtra("ListSize", (long) downloadService.getSongs().size());
|
avrcpIntent.putExtra("ListSize", (long) downloadService.getSongs().size());
|
||||||
|
|
||||||
switch (downloadService.getPlayerState()){
|
switch (downloadService.getPlayerState()) {
|
||||||
case STARTED:
|
case STARTED:
|
||||||
avrcpIntent.putExtra("playing", true);
|
avrcpIntent.putExtra("playing", true);
|
||||||
break;
|
break;
|
||||||
|
@ -20,7 +20,6 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.PlayerState;
|
import net.nullsum.audinaut.domain.PlayerState;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
@ -28,24 +27,23 @@ import net.nullsum.audinaut.util.Constants;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class AudioNoisyReceiver extends BroadcastReceiver {
|
public class AudioNoisyReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = AudioNoisyReceiver.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
// Don't do anything if downloadService is not started
|
// Don't do anything if downloadService is not started
|
||||||
if(downloadService == null) {
|
if (downloadService == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals (intent.getAction ())) {
|
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
|
||||||
if((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) {
|
if ((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) {
|
||||||
SharedPreferences prefs = Util.getPreferences(downloadService);
|
SharedPreferences prefs = Util.getPreferences(downloadService);
|
||||||
int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0"));
|
int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0"));
|
||||||
if(pausePref == 0) {
|
if (pausePref == 0) {
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@ import android.content.Intent;
|
|||||||
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
import net.nullsum.audinaut.service.HeadphoneListenerService;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class BootReceiver extends BroadcastReceiver {
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(Util.shouldStartOnHeadphones(context)) {
|
if (Util.shouldStartOnHeadphones(context)) {
|
||||||
Intent serviceIntent = new Intent();
|
Intent serviceIntent = new Intent();
|
||||||
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
||||||
context.startService(serviceIntent);
|
context.startService(serviceIntent);
|
||||||
|
@ -18,19 +18,17 @@ package net.nullsum.audinaut.receiver;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class HeadphonePlugReceiver extends BroadcastReceiver {
|
public class HeadphonePlugReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = HeadphonePlugReceiver.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
|
if (Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
|
||||||
int headphoneState = intent.getIntExtra("state", -1);
|
int headphoneState = intent.getIntExtra("state", -1);
|
||||||
if(headphoneState == 1 && Util.shouldStartOnHeadphones(context)) {
|
if (headphoneState == 1 && Util.shouldStartOnHeadphones(context)) {
|
||||||
Intent start = new Intent(context, DownloadService.class);
|
Intent start = new Intent(context, DownloadService.class);
|
||||||
start.setAction(DownloadService.START_PLAY);
|
start.setAction(DownloadService.START_PLAY);
|
||||||
context.startService(start);
|
context.startService(start);
|
||||||
|
@ -36,8 +36,8 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||||
if(DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP ||
|
if (DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP ||
|
||||||
event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
|
event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
|
||||||
Log.w(TAG, "Ignore keycode event because downloadService is off");
|
Log.w(TAG, "Ignore keycode event because downloadService is off");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -19,17 +19,15 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public class PlayActionReceiver extends BroadcastReceiver {
|
public class PlayActionReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = PlayActionReceiver.class.getSimpleName();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
|
if (intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
|
||||||
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||||
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
||||||
|
|
||||||
|
@ -18,17 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -36,41 +25,43 @@ import android.util.Log;
|
|||||||
import net.nullsum.audinaut.domain.Artist;
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.domain.Indexes;
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.domain.SearchCritera;
|
import net.nullsum.audinaut.domain.SearchCritera;
|
||||||
import net.nullsum.audinaut.domain.SearchResult;
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
import net.nullsum.audinaut.domain.User;
|
import net.nullsum.audinaut.domain.User;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.SongDBHandler;
|
import net.nullsum.audinaut.util.SongDBHandler;
|
||||||
import net.nullsum.audinaut.util.TimeLimitedCache;
|
import net.nullsum.audinaut.util.TimeLimitedCache;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class CachedMusicService implements MusicService {
|
public class CachedMusicService implements MusicService {
|
||||||
|
public static final int CACHE_UPDATE_LIST = 1;
|
||||||
|
private static final int CACHE_UPDATE_METADATA = 2;
|
||||||
private static final String TAG = CachedMusicService.class.getSimpleName();
|
private static final String TAG = CachedMusicService.class.getSimpleName();
|
||||||
|
|
||||||
private static final int MUSIC_DIR_CACHE_SIZE = 20;
|
|
||||||
private static final int TTL_MUSIC_DIR = 5 * 60; // Five minutes
|
|
||||||
public static final int CACHE_UPDATE_LIST = 1;
|
|
||||||
public static final int CACHE_UPDATE_METADATA = 2;
|
|
||||||
private static final int CACHED_LAST_FM = 24 * 60;
|
|
||||||
|
|
||||||
private final RESTMusicService musicService;
|
private final RESTMusicService musicService;
|
||||||
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
|
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<>(60 * 60);
|
||||||
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(3600, TimeUnit.SECONDS);
|
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<>(3600);
|
||||||
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
|
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<>(10 * 3600);
|
||||||
private String restUrl;
|
private String restUrl;
|
||||||
private String musicFolderId;
|
private String musicFolderId;
|
||||||
private boolean isTagBrowsing = false;
|
|
||||||
|
|
||||||
public CachedMusicService(RESTMusicService musicService) {
|
public CachedMusicService(RESTMusicService musicService) {
|
||||||
this.musicService = musicService;
|
this.musicService = musicService;
|
||||||
@ -90,13 +81,13 @@ public class CachedMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
List<MusicFolder> result = cachedMusicFolders.get();
|
List<MusicFolder> result = cachedMusicFolders.get();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
if(!refresh) {
|
if (!refresh) {
|
||||||
result = FileUtil.deserialize(context, getCacheName(context, "musicFolders"), ArrayList.class);
|
result = FileUtil.deserialize(context, getCacheName(context, "musicFolders"), ArrayList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null) {
|
if (result == null) {
|
||||||
result = musicService.getMusicFolders(refresh, context, progressListener);
|
result = musicService.getMusicFolders(refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, new ArrayList<MusicFolder>(result), getCacheName(context, "musicFolders"));
|
FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "musicFolders"));
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicFolder.sort(result);
|
MusicFolder.sort(result);
|
||||||
@ -114,13 +105,13 @@ public class CachedMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
Indexes result = cachedIndexes.get();
|
Indexes result = cachedIndexes.get();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
String name = Util.isTagBrowsing(context, musicService.getInstance(context)) ? "artists" : "indexes";
|
String name = "artists";
|
||||||
name = getCacheName(context, name, musicFolderId);
|
name = getCacheName(context, name, musicFolderId);
|
||||||
if(!refresh) {
|
if (!refresh) {
|
||||||
result = FileUtil.deserialize(context, name, Indexes.class);
|
result = FileUtil.deserialize(context, name, Indexes.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null) {
|
if (result == null) {
|
||||||
result = musicService.getIndexes(musicFolderId, refresh, context, progressListener);
|
result = musicService.getIndexes(musicFolderId, refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, result, name);
|
FileUtil.serialize(context, result, name);
|
||||||
}
|
}
|
||||||
@ -133,7 +124,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
public MusicDirectory getMusicDirectory(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
public MusicDirectory getMusicDirectory(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
||||||
MusicDirectory dir = null;
|
MusicDirectory dir = null;
|
||||||
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "directory", id), MusicDirectory.class);
|
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "directory", id), MusicDirectory.class);
|
||||||
if(!refresh && cached != null) {
|
if (!refresh && cached != null) {
|
||||||
dir = cached;
|
dir = cached;
|
||||||
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@ -153,11 +144,11 @@ public class CachedMusicService implements MusicService {
|
|||||||
// Update which entries exist
|
// Update which entries exist
|
||||||
@Override
|
@Override
|
||||||
public void done(Void result) {
|
public void done(Void result) {
|
||||||
if(progressListener != null) {
|
if (progressListener != null) {
|
||||||
if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) {
|
if (cached.updateEntriesList(context, refreshed)) {
|
||||||
progressListener.updateCache(CACHE_UPDATE_LIST);
|
progressListener.updateCache(CACHE_UPDATE_LIST);
|
||||||
}
|
}
|
||||||
if(metadataUpdated) {
|
if (metadataUpdated) {
|
||||||
progressListener.updateCache(CACHE_UPDATE_METADATA);
|
progressListener.updateCache(CACHE_UPDATE_METADATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +161,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener);
|
dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener);
|
||||||
updateAllSongs(context, dir);
|
updateAllSongs(context, dir);
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, "directory", id));
|
FileUtil.serialize(context, dir, getCacheName(context, "directory", id));
|
||||||
@ -178,7 +169,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
// If a cached copy exists to check against, look for removes
|
// If a cached copy exists to check against, look for removes
|
||||||
deleteRemovedEntries(context, dir, cached);
|
deleteRemovedEntries(context, dir, cached);
|
||||||
}
|
}
|
||||||
dir.sortChildren(context, musicService.getInstance(context));
|
dir.sortChildren(context);
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
@ -187,7 +178,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
public MusicDirectory getArtist(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
public MusicDirectory getArtist(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
||||||
MusicDirectory dir = null;
|
MusicDirectory dir = null;
|
||||||
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "artist", id), MusicDirectory.class);
|
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "artist", id), MusicDirectory.class);
|
||||||
if(!refresh && cached != null) {
|
if (!refresh && cached != null) {
|
||||||
dir = cached;
|
dir = cached;
|
||||||
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@ -205,8 +196,8 @@ public class CachedMusicService implements MusicService {
|
|||||||
// Update which entries exist
|
// Update which entries exist
|
||||||
@Override
|
@Override
|
||||||
public void done(Void result) {
|
public void done(Void result) {
|
||||||
if(progressListener != null) {
|
if (progressListener != null) {
|
||||||
if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) {
|
if (cached.updateEntriesList(context, refreshed)) {
|
||||||
progressListener.updateCache(CACHE_UPDATE_LIST);
|
progressListener.updateCache(CACHE_UPDATE_LIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,14 +210,14 @@ public class CachedMusicService implements MusicService {
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = musicService.getArtist(id, name, refresh, context, progressListener);
|
dir = musicService.getArtist(id, name, refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, "artist", id));
|
FileUtil.serialize(context, dir, getCacheName(context, "artist", id));
|
||||||
|
|
||||||
// If a cached copy exists to check against, look for removes
|
// If a cached copy exists to check against, look for removes
|
||||||
deleteRemovedEntries(context, dir, cached);
|
deleteRemovedEntries(context, dir, cached);
|
||||||
}
|
}
|
||||||
dir.sortChildren(context, musicService.getInstance(context));
|
dir.sortChildren(context);
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
@ -235,7 +226,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
public MusicDirectory getAlbum(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbum(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception {
|
||||||
MusicDirectory dir = null;
|
MusicDirectory dir = null;
|
||||||
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "album", id), MusicDirectory.class);
|
final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "album", id), MusicDirectory.class);
|
||||||
if(!refresh && cached != null) {
|
if (!refresh && cached != null) {
|
||||||
dir = cached;
|
dir = cached;
|
||||||
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@ -255,11 +246,11 @@ public class CachedMusicService implements MusicService {
|
|||||||
// Update which entries exist
|
// Update which entries exist
|
||||||
@Override
|
@Override
|
||||||
public void done(Void result) {
|
public void done(Void result) {
|
||||||
if(progressListener != null) {
|
if (progressListener != null) {
|
||||||
if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) {
|
if (cached.updateEntriesList(context, refreshed)) {
|
||||||
progressListener.updateCache(CACHE_UPDATE_LIST);
|
progressListener.updateCache(CACHE_UPDATE_LIST);
|
||||||
}
|
}
|
||||||
if(metadataUpdated) {
|
if (metadataUpdated) {
|
||||||
progressListener.updateCache(CACHE_UPDATE_METADATA);
|
progressListener.updateCache(CACHE_UPDATE_METADATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,7 +263,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = musicService.getAlbum(id, name, refresh, context, progressListener);
|
dir = musicService.getAlbum(id, name, refresh, context, progressListener);
|
||||||
updateAllSongs(context, dir);
|
updateAllSongs(context, dir);
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, "album", id));
|
FileUtil.serialize(context, dir, getCacheName(context, "album", id));
|
||||||
@ -280,7 +271,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
// If a cached copy exists to check against, look for removes
|
// If a cached copy exists to check against, look for removes
|
||||||
deleteRemovedEntries(context, dir, cached);
|
deleteRemovedEntries(context, dir, cached);
|
||||||
}
|
}
|
||||||
dir.sortChildren(context, musicService.getInstance(context));
|
dir.sortChildren(context);
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
@ -294,16 +285,16 @@ public class CachedMusicService implements MusicService {
|
|||||||
public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||||
MusicDirectory dir = null;
|
MusicDirectory dir = null;
|
||||||
MusicDirectory cachedPlaylist = FileUtil.deserialize(context, getCacheName(context, "playlist", id), MusicDirectory.class);
|
MusicDirectory cachedPlaylist = FileUtil.deserialize(context, getCacheName(context, "playlist", id), MusicDirectory.class);
|
||||||
if(!refresh) {
|
if (!refresh) {
|
||||||
dir = cachedPlaylist;
|
dir = cachedPlaylist;
|
||||||
}
|
}
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = musicService.getPlaylist(refresh, id, name, context, progressListener);
|
dir = musicService.getPlaylist(refresh, id, name, context, progressListener);
|
||||||
updateAllSongs(context, dir);
|
updateAllSongs(context, dir);
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, "playlist", id));
|
FileUtil.serialize(context, dir, getCacheName(context, "playlist", id));
|
||||||
|
|
||||||
File playlistFile = FileUtil.getPlaylistFile(context, Util.getServerName(context, musicService.getInstance(context)), dir.getName());
|
File playlistFile = FileUtil.getPlaylistFile(context, Util.getServerName(context, musicService.getInstance(context)), dir.getName());
|
||||||
if(cachedPlaylist == null || !playlistFile.exists() || !cachedPlaylist.getChildren().equals(dir.getChildren())) {
|
if (cachedPlaylist == null || !playlistFile.exists() || !cachedPlaylist.getChildren().equals(dir.getChildren())) {
|
||||||
FileUtil.writePlaylistFile(context, playlistFile, dir);
|
FileUtil.writePlaylistFile(context, playlistFile, dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,13 +306,13 @@ public class CachedMusicService implements MusicService {
|
|||||||
checkSettingsChanged(context);
|
checkSettingsChanged(context);
|
||||||
List<Playlist> result = refresh ? null : cachedPlaylists.get();
|
List<Playlist> result = refresh ? null : cachedPlaylists.get();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
if(!refresh) {
|
if (!refresh) {
|
||||||
result = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class);
|
result = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null) {
|
if (result == null) {
|
||||||
result = musicService.getPlaylists(refresh, context, progressListener);
|
result = musicService.getPlaylists(refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, new ArrayList<Playlist>(result), getCacheName(context, "playlist"));
|
FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "playlist"));
|
||||||
}
|
}
|
||||||
cachedPlaylists.set(result);
|
cachedPlaylists.set(result);
|
||||||
}
|
}
|
||||||
@ -381,9 +372,9 @@ public class CachedMusicService implements MusicService {
|
|||||||
boolean supposedToUnpin = false;
|
boolean supposedToUnpin = false;
|
||||||
|
|
||||||
// Remove in reverse order so indexes are still correct as we iterate through
|
// Remove in reverse order so indexes are still correct as we iterate through
|
||||||
for(ListIterator<Integer> iterator = toRemove.listIterator(toRemove.size()); iterator.hasPrevious(); ) {
|
for (ListIterator<Integer> iterator = toRemove.listIterator(toRemove.size()); iterator.hasPrevious(); ) {
|
||||||
int index = iterator.previous();
|
int index = iterator.previous();
|
||||||
if(supposedToUnpin) {
|
if (supposedToUnpin) {
|
||||||
Entry entry = objects.get(index);
|
Entry entry = objects.get(index);
|
||||||
DownloadFile file = new DownloadFile(context, entry, true);
|
DownloadFile file = new DownloadFile(context, entry, true);
|
||||||
file.unpin();
|
file.unpin();
|
||||||
@ -439,24 +430,17 @@ public class CachedMusicService implements MusicService {
|
|||||||
String recentlyAddedFile = getCacheName(context, type);
|
String recentlyAddedFile = getCacheName(context, type);
|
||||||
ArrayList<String> recents = FileUtil.deserialize(context, recentlyAddedFile, ArrayList.class);
|
ArrayList<String> recents = FileUtil.deserialize(context, recentlyAddedFile, ArrayList.class);
|
||||||
if (recents == null) {
|
if (recents == null) {
|
||||||
recents = new ArrayList<String>();
|
recents = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any new items
|
// Add any new items
|
||||||
final int instance = musicService.getInstance(context);
|
|
||||||
isTagBrowsing = Util.isTagBrowsing(context, instance);
|
|
||||||
for (final Entry album : dir.getChildren()) {
|
for (final Entry album : dir.getChildren()) {
|
||||||
if (!recents.contains(album.getId())) {
|
if (!recents.contains(album.getId())) {
|
||||||
recents.add(album.getId());
|
recents.add(album.getId());
|
||||||
|
|
||||||
String cacheName, parent;
|
String cacheName, parent;
|
||||||
if (isTagBrowsing) {
|
cacheName = "artist";
|
||||||
cacheName = "artist";
|
parent = album.getArtistId();
|
||||||
parent = album.getArtistId();
|
|
||||||
} else {
|
|
||||||
cacheName = "directory";
|
|
||||||
parent = album.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add album to artist
|
// Add album to artist
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
@ -492,7 +476,7 @@ public class CachedMusicService implements MusicService {
|
|||||||
artist.setId(album.getId());
|
artist.setId(album.getId());
|
||||||
artist.setName(album.getTitle());
|
artist.setName(album.getTitle());
|
||||||
|
|
||||||
new IndexesUpdater(context, isTagBrowsing ? "artists" : "indexes") {
|
new IndexesUpdater(context) {
|
||||||
private boolean changed = false;
|
private boolean changed = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -530,17 +514,17 @@ public class CachedMusicService implements MusicService {
|
|||||||
|
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, type, Integer.toString(offset)));
|
FileUtil.serialize(context, dir, getCacheName(context, type, Integer.toString(offset)));
|
||||||
return dir;
|
return dir;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, "Failed to refresh album list: ", e);
|
Log.w(TAG, "Failed to refresh album list: ", e);
|
||||||
if(refresh) {
|
if (refresh) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type, Integer.toString(offset)), MusicDirectory.class);
|
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type, Integer.toString(offset)), MusicDirectory.class);
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
// If we are at start and no cache, throw error higher
|
// If we are at start and no cache, throw error higher
|
||||||
if(offset == 0) {
|
if (offset == 0) {
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just pretend we are at the end of the list
|
// Otherwise just pretend we are at the end of the list
|
||||||
@ -558,17 +542,17 @@ public class CachedMusicService implements MusicService {
|
|||||||
MusicDirectory dir = musicService.getAlbumList(type, extra, size, offset, refresh, context, progressListener);
|
MusicDirectory dir = musicService.getAlbumList(type, extra, size, offset, refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, dir, getCacheName(context, type + extra, Integer.toString(offset)));
|
FileUtil.serialize(context, dir, getCacheName(context, type + extra, Integer.toString(offset)));
|
||||||
return dir;
|
return dir;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, "Failed to refresh album list: ", e);
|
Log.w(TAG, "Failed to refresh album list: ", e);
|
||||||
if(refresh) {
|
if (refresh) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type + extra, Integer.toString(offset)), MusicDirectory.class);
|
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type + extra, Integer.toString(offset)), MusicDirectory.class);
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
// If we are at start and no cache, throw error higher
|
// If we are at start and no cache, throw error higher
|
||||||
if(offset == 0) {
|
if (offset == 0) {
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just pretend we are at the end of the list
|
// Otherwise just pretend we are at the end of the list
|
||||||
@ -585,11 +569,6 @@ public class CachedMusicService implements MusicService {
|
|||||||
return musicService.getSongList(type, size, offset, context, progressListener);
|
return musicService.getSongList(type, size, offset, context, progressListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
return musicService.getRandomSongs(size, artistId, context, progressListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
||||||
return musicService.getRandomSongs(size, folder, genre, startYear, endYear, context, progressListener);
|
return musicService.getRandomSongs(size, folder, genre, startYear, endYear, context, progressListener);
|
||||||
@ -609,13 +588,13 @@ public class CachedMusicService implements MusicService {
|
|||||||
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Genre> result = null;
|
List<Genre> result = null;
|
||||||
|
|
||||||
if(!refresh) {
|
if (!refresh) {
|
||||||
result = FileUtil.deserialize(context, getCacheName(context, "genre"), ArrayList.class);
|
result = FileUtil.deserialize(context, getCacheName(context, "genre"), ArrayList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null) {
|
if (result == null) {
|
||||||
result = musicService.getGenres(refresh, context, progressListener);
|
result = musicService.getGenres(refresh, context, progressListener);
|
||||||
FileUtil.serialize(context, new ArrayList<Genre>(result), getCacheName(context, "genre"));
|
FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "genre"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -628,12 +607,12 @@ public class CachedMusicService implements MusicService {
|
|||||||
FileUtil.serialize(context, dir, getCacheName(context, "genreSongs", Integer.toString(offset)));
|
FileUtil.serialize(context, dir, getCacheName(context, "genreSongs", Integer.toString(offset)));
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, "genreSongs", Integer.toString(offset)), MusicDirectory.class);
|
MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, "genreSongs", Integer.toString(offset)), MusicDirectory.class);
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
// If we are at start and no cache, throw error higher
|
// If we are at start and no cache, throw error higher
|
||||||
if(offset == 0) {
|
if (offset == 0) {
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just pretend we are at the end of the list
|
// Otherwise just pretend we are at the end of the list
|
||||||
@ -652,32 +631,17 @@ public class CachedMusicService implements MusicService {
|
|||||||
try {
|
try {
|
||||||
result = musicService.getUser(refresh, username, context, progressListener);
|
result = musicService.getUser(refresh, username, context, progressListener);
|
||||||
FileUtil.serialize(context, result, getCacheName(context, "user-" + username));
|
FileUtil.serialize(context, result, getCacheName(context, "user-" + username));
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null && !refresh) {
|
if (result == null && !refresh) {
|
||||||
result = FileUtil.deserialize(context, getCacheName(context, "user-" + username), User.class);
|
result = FileUtil.deserialize(context, getCacheName(context, "user-" + username), User.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
|
||||||
return musicService.getBitmap(url, size, context, progressListener, task);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void savePlayQueue(List<Entry> songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
musicService.savePlayQueue(songs, currentPlaying, position, context, progressListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
return musicService.getPlayQueue(context, progressListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInstance(Integer instance) throws Exception {
|
public void setInstance(Integer instance) throws Exception {
|
||||||
musicService.setInstance(instance);
|
musicService.setInstance(instance);
|
||||||
@ -687,57 +651,76 @@ public class CachedMusicService implements MusicService {
|
|||||||
String s = musicService.getRestUrl(context, null, false) + id;
|
String s = musicService.getRestUrl(context, null, false) + id;
|
||||||
return name + "-" + s.hashCode() + ".ser";
|
return name + "-" + s.hashCode() + ".ser";
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCacheName(Context context, String name) {
|
private String getCacheName(Context context, String name) {
|
||||||
String s = musicService.getRestUrl(context, null, false);
|
String s = musicService.getRestUrl(context, null, false);
|
||||||
return name + "-" + s.hashCode() + ".ser";
|
return name + "-" + s.hashCode() + ".ser";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteRemovedEntries(Context context, MusicDirectory dir, MusicDirectory cached) {
|
private void deleteRemovedEntries(Context context, MusicDirectory dir, MusicDirectory cached) {
|
||||||
if(cached != null) {
|
if (cached != null) {
|
||||||
List<Entry> oldList = new ArrayList<Entry>();
|
List<Entry> oldList = new ArrayList<>();
|
||||||
oldList.addAll(cached.getChildren());
|
oldList.addAll(cached.getChildren());
|
||||||
|
oldList.removeAll(dir.getChildren());
|
||||||
// Remove all current items from old list
|
|
||||||
for(Entry entry: dir.getChildren()) {
|
|
||||||
oldList.remove(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anything remaining has been removed from server
|
// Anything remaining has been removed from server
|
||||||
MediaStoreService store = new MediaStoreService(context);
|
MediaStoreService store = new MediaStoreService(context);
|
||||||
for(Entry entry: oldList) {
|
for (Entry entry : oldList) {
|
||||||
File file = FileUtil.getEntryFile(context, entry);
|
File file = FileUtil.getEntryFile(context, entry);
|
||||||
FileUtil.recursiveDelete(file, store);
|
FileUtil.recursiveDelete(file, store);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateAllSongs(Context context, MusicDirectory dir) {
|
||||||
|
List<Entry> songs = dir.getSongs();
|
||||||
|
if (!songs.isEmpty()) {
|
||||||
|
SongDBHandler.getHandler(context).addSongs(musicService.getInstance(context), songs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSettingsChanged(Context context) {
|
||||||
|
int instance = musicService.getInstance(context);
|
||||||
|
String newUrl = musicService.getRestUrl(context, null, false);
|
||||||
|
if (!Util.equals(newUrl, restUrl)) {
|
||||||
|
cachedMusicFolders.clear();
|
||||||
|
cachedIndexes.clear();
|
||||||
|
cachedPlaylists.clear();
|
||||||
|
restUrl = newUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
String newMusicFolderId = Util.getSelectedMusicFolderId(context, instance);
|
||||||
|
if (!Util.equals(newMusicFolderId, musicFolderId)) {
|
||||||
|
cachedIndexes.clear();
|
||||||
|
musicFolderId = newMusicFolderId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private abstract class SerializeUpdater<T> {
|
private abstract class SerializeUpdater<T> {
|
||||||
final Context context;
|
final Context context;
|
||||||
final String cacheName;
|
final String cacheName;
|
||||||
final boolean singleUpdate;
|
final boolean singleUpdate;
|
||||||
|
|
||||||
public SerializeUpdater(Context context, String cacheName) {
|
public SerializeUpdater(Context context) {
|
||||||
this(context, cacheName, true);
|
|
||||||
}
|
|
||||||
public SerializeUpdater(Context context, String cacheName, boolean singleUpdate) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.cacheName = getCacheName(context, cacheName);
|
this.cacheName = getCacheName(context, "playlist");
|
||||||
this.singleUpdate = singleUpdate;
|
this.singleUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SerializeUpdater(Context context, String cacheName, String id) {
|
public SerializeUpdater(Context context, String cacheName, String id) {
|
||||||
this(context, cacheName, id, true);
|
|
||||||
}
|
|
||||||
public SerializeUpdater(Context context, String cacheName, String id, boolean singleUpdate) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.cacheName = getCacheName(context, cacheName, id);
|
this.cacheName = getCacheName(context, cacheName, id);
|
||||||
this.singleUpdate = singleUpdate;
|
this.singleUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<T> getArrayList() {
|
public ArrayList<T> getArrayList() {
|
||||||
return FileUtil.deserialize(context, cacheName, ArrayList.class);
|
return FileUtil.deserialize(context, cacheName, ArrayList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean checkResult(T check);
|
public abstract boolean checkResult(T check);
|
||||||
|
|
||||||
public abstract void updateResult(List<T> objects, T result);
|
public abstract void updateResult(List<T> objects, T result);
|
||||||
|
|
||||||
public void save(ArrayList<T> objects) {
|
public void save(ArrayList<T> objects) {
|
||||||
FileUtil.serialize(context, objects, cacheName);
|
FileUtil.serialize(context, objects, cacheName);
|
||||||
}
|
}
|
||||||
@ -746,47 +729,35 @@ public class CachedMusicService implements MusicService {
|
|||||||
ArrayList<T> objects = getArrayList();
|
ArrayList<T> objects = getArrayList();
|
||||||
|
|
||||||
// Only execute if something to check against
|
// Only execute if something to check against
|
||||||
if(objects != null) {
|
if (objects != null) {
|
||||||
List<T> results = new ArrayList<T>();
|
List<T> results = new ArrayList<>();
|
||||||
for(T check: objects) {
|
for (T check : objects) {
|
||||||
if(checkResult(check)) {
|
if (checkResult(check)) {
|
||||||
results.add(check);
|
results.add(check);
|
||||||
if(singleUpdate) {
|
if (singleUpdate) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through and update each object matched
|
// Iterate through and update each object matched
|
||||||
for(T result: results) {
|
for (T result : results) {
|
||||||
updateResult(objects, result);
|
updateResult(objects, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only reserialize if at least one match was found
|
// Only reserialize if at least one match was found
|
||||||
if(results.size() > 0) {
|
if (results.size() > 0) {
|
||||||
save(objects);
|
save(objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private abstract class UserUpdater extends SerializeUpdater<User> {
|
|
||||||
String username;
|
|
||||||
|
|
||||||
public UserUpdater(Context context, String username) {
|
|
||||||
super(context, "users");
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(User check) {
|
|
||||||
return username.equals(check.getUsername());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private abstract class PlaylistUpdater extends SerializeUpdater<Playlist> {
|
private abstract class PlaylistUpdater extends SerializeUpdater<Playlist> {
|
||||||
String id;
|
final String id;
|
||||||
|
|
||||||
public PlaylistUpdater(Context context, String id) {
|
public PlaylistUpdater(Context context, String id) {
|
||||||
super(context, "playlist");
|
super(context);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,199 +766,45 @@ public class CachedMusicService implements MusicService {
|
|||||||
return id.equals(check.getId());
|
return id.equals(check.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class MusicDirectoryUpdater extends SerializeUpdater<Entry> {
|
private abstract class MusicDirectoryUpdater extends SerializeUpdater<Entry> {
|
||||||
protected MusicDirectory musicDirectory;
|
MusicDirectory musicDirectory;
|
||||||
|
|
||||||
public MusicDirectoryUpdater(Context context, String cacheName, String id) {
|
public MusicDirectoryUpdater(Context context, String cacheName, String id) {
|
||||||
super(context, cacheName, id, true);
|
super(context, cacheName, id);
|
||||||
}
|
|
||||||
public MusicDirectoryUpdater(Context context, String cacheName, String id, boolean singleUpdate) {
|
|
||||||
super(context, cacheName, id, singleUpdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<Entry> getArrayList() {
|
public ArrayList<Entry> getArrayList() {
|
||||||
musicDirectory = FileUtil.deserialize(context, cacheName, MusicDirectory.class);
|
musicDirectory = FileUtil.deserialize(context, cacheName, MusicDirectory.class);
|
||||||
if(musicDirectory != null) {
|
if (musicDirectory != null) {
|
||||||
return new ArrayList<>(musicDirectory.getChildren());
|
return new ArrayList<>(musicDirectory.getChildren());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(ArrayList<Entry> objects) {
|
public void save(ArrayList<Entry> objects) {
|
||||||
musicDirectory.replaceChildren(objects);
|
musicDirectory.replaceChildren(objects);
|
||||||
FileUtil.serialize(context, musicDirectory, cacheName);
|
FileUtil.serialize(context, musicDirectory, cacheName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private abstract class PlaylistDirectoryUpdater {
|
|
||||||
Context context;
|
|
||||||
|
|
||||||
public PlaylistDirectoryUpdater(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean checkResult(Entry check);
|
|
||||||
public abstract void updateResult(Entry result);
|
|
||||||
|
|
||||||
public void execute() {
|
|
||||||
List<Playlist> playlists = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class);
|
|
||||||
if(playlists == null) {
|
|
||||||
// No playlist list cache, nothing to update!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Playlist playlist: playlists) {
|
|
||||||
new MusicDirectoryUpdater(context, "playlist", playlist.getId(), false) {
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(Entry check) {
|
|
||||||
return PlaylistDirectoryUpdater.this.checkResult(check);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateResult(List<Entry> objects, Entry result) {
|
|
||||||
PlaylistDirectoryUpdater.this.updateResult(result);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private abstract class GenericEntryUpdater {
|
|
||||||
Context context;
|
|
||||||
List<Entry> entries;
|
|
||||||
|
|
||||||
public GenericEntryUpdater(Context context, Entry entry) {
|
|
||||||
this.context = context;
|
|
||||||
this.entries = Arrays.asList(entry);
|
|
||||||
}
|
|
||||||
public GenericEntryUpdater(Context context, List<Entry> entries) {
|
|
||||||
this.context = context;
|
|
||||||
this.entries = entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkResult(Entry entry, Entry check) {
|
|
||||||
return entry.getId().equals(check.getId());
|
|
||||||
}
|
|
||||||
public abstract void updateResult(Entry result);
|
|
||||||
|
|
||||||
public void execute() {
|
|
||||||
String cacheName, parent;
|
|
||||||
// Make sure it is up to date
|
|
||||||
isTagBrowsing = Util.isTagBrowsing(context, musicService.getInstance(context));
|
|
||||||
|
|
||||||
// Run through each entry, trying to update the directory it is in
|
|
||||||
final List<Entry> songs = new ArrayList<Entry>();
|
|
||||||
for(final Entry entry: entries) {
|
|
||||||
if(isTagBrowsing) {
|
|
||||||
// If starring album, needs to reference artist instead
|
|
||||||
if(entry.isDirectory()) {
|
|
||||||
if(entry.isAlbum()) {
|
|
||||||
cacheName = "artist";
|
|
||||||
parent = entry.getArtistId();
|
|
||||||
} else {
|
|
||||||
cacheName = "artists";
|
|
||||||
parent = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cacheName = "album";
|
|
||||||
parent = entry.getAlbumId();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(entry.isDirectory() && !entry.isAlbum()) {
|
|
||||||
cacheName = "indexes";
|
|
||||||
parent = null;
|
|
||||||
} else {
|
|
||||||
cacheName = "directory";
|
|
||||||
parent = entry.getParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent is only null when it is an artist
|
|
||||||
if(parent == null) {
|
|
||||||
new IndexesUpdater(context, cacheName) {
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(Artist check) {
|
|
||||||
return GenericEntryUpdater.this.checkResult(entry, new Entry(check));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateResult(List<Artist> objects, Artist result) {
|
|
||||||
// Don't try to put anything here, as the Entry update method will not be called since it's a artist!
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
} else {
|
|
||||||
new MusicDirectoryUpdater(context, cacheName, parent) {
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(Entry check) {
|
|
||||||
return GenericEntryUpdater.this.checkResult(entry, check);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateResult(List<Entry> objects, Entry result) {
|
|
||||||
GenericEntryUpdater.this.updateResult(result);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
songs.add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only run through playlists once and check each song against it
|
|
||||||
if(songs.size() > 0) {
|
|
||||||
new PlaylistDirectoryUpdater(context) {
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(Entry check) {
|
|
||||||
for(Entry entry: songs) {
|
|
||||||
if(GenericEntryUpdater.this.checkResult(entry, check)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateResult(Entry result) {
|
|
||||||
GenericEntryUpdater.this.updateResult(result);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class StarUpdater extends GenericEntryUpdater {
|
|
||||||
public StarUpdater(Context context, List<Entry> entries) {
|
|
||||||
super(context, entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkResult(Entry entry, Entry check) {
|
|
||||||
if (!entry.getId().equals(check.getId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateResult(Entry result) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private abstract class IndexesUpdater extends SerializeUpdater<Artist> {
|
private abstract class IndexesUpdater extends SerializeUpdater<Artist> {
|
||||||
Indexes indexes;
|
Indexes indexes;
|
||||||
|
|
||||||
IndexesUpdater(Context context, String name) {
|
IndexesUpdater(Context context) {
|
||||||
super(context, name, Util.getSelectedMusicFolderId(context, musicService.getInstance(context)));
|
super(context, "artists", Util.getSelectedMusicFolderId(context, musicService.getInstance(context)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<Artist> getArrayList() {
|
public ArrayList<Artist> getArrayList() {
|
||||||
indexes = FileUtil.deserialize(context, cacheName, Indexes.class);
|
indexes = FileUtil.deserialize(context, cacheName, Indexes.class);
|
||||||
if(indexes == null) {
|
if (indexes == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Artist> artists = new ArrayList<Artist>();
|
ArrayList<Artist> artists = new ArrayList<>();
|
||||||
artists.addAll(indexes.getArtists());
|
artists.addAll(indexes.getArtists());
|
||||||
artists.addAll(indexes.getShortcuts());
|
artists.addAll(indexes.getShortcuts());
|
||||||
return artists;
|
return artists;
|
||||||
@ -999,34 +816,4 @@ public class CachedMusicService implements MusicService {
|
|||||||
cachedIndexes.set(indexes);
|
cachedIndexes.set(indexes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateAllSongs(Context context, MusicDirectory dir) {
|
|
||||||
List<Entry> songs = dir.getSongs();
|
|
||||||
if(!songs.isEmpty()) {
|
|
||||||
SongDBHandler.getHandler(context).addSongs(musicService.getInstance(context), songs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkSettingsChanged(Context context) {
|
|
||||||
int instance = musicService.getInstance(context);
|
|
||||||
String newUrl = musicService.getRestUrl(context, null, false);
|
|
||||||
boolean newIsTagBrowsing = Util.isTagBrowsing(context, instance);
|
|
||||||
if (!Util.equals(newUrl, restUrl) || isTagBrowsing != newIsTagBrowsing) {
|
|
||||||
cachedMusicFolders.clear();
|
|
||||||
cachedIndexes.clear();
|
|
||||||
cachedPlaylists.clear();
|
|
||||||
restUrl = newUrl;
|
|
||||||
isTagBrowsing = newIsTagBrowsing;
|
|
||||||
}
|
|
||||||
|
|
||||||
String newMusicFolderId = Util.getSelectedMusicFolderId(context, instance);
|
|
||||||
if(!Util.equals(newMusicFolderId, musicFolderId)) {
|
|
||||||
cachedIndexes.clear();
|
|
||||||
musicFolderId = newMusicFolderId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RESTMusicService getMusicService() {
|
|
||||||
return musicService;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
@ -38,6 +31,13 @@ import net.nullsum.audinaut.util.FileUtil;
|
|||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,16 +54,15 @@ public class DownloadFile implements BufferFile {
|
|||||||
private final File saveFile;
|
private final File saveFile;
|
||||||
|
|
||||||
private final MediaStoreService mediaStoreService;
|
private final MediaStoreService mediaStoreService;
|
||||||
|
private final boolean save;
|
||||||
|
private final Long contentLength = null;
|
||||||
private DownloadTask downloadTask;
|
private DownloadTask downloadTask;
|
||||||
private boolean save;
|
|
||||||
private boolean failedDownload = false;
|
private boolean failedDownload = false;
|
||||||
private int failed = 0;
|
private int failed = 0;
|
||||||
private int bitRate;
|
private int bitRate;
|
||||||
private boolean isPlaying = false;
|
private boolean isPlaying = false;
|
||||||
private boolean saveWhenDone = false;
|
private boolean saveWhenDone = false;
|
||||||
private boolean completeWhenDone = false;
|
private boolean completeWhenDone = false;
|
||||||
private Long contentLength = null;
|
|
||||||
private long currentSpeed = 0;
|
|
||||||
private boolean rateLimit = false;
|
private boolean rateLimit = false;
|
||||||
|
|
||||||
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
|
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
|
||||||
@ -82,19 +81,16 @@ public class DownloadFile implements BufferFile {
|
|||||||
public MusicDirectory.Entry getSong() {
|
public MusicDirectory.Entry getSong() {
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSong() {
|
public boolean isSong() {
|
||||||
return song.isSong();
|
return song.isSong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective bit rate.
|
* Returns the effective bit rate.
|
||||||
*/
|
*/
|
||||||
public int getBitRate() {
|
public int getBitRate() {
|
||||||
if(!partialFile.exists()) {
|
if (!partialFile.exists()) {
|
||||||
bitRate = getActualBitrate();
|
bitRate = getActualBitrate();
|
||||||
}
|
}
|
||||||
if (bitRate > 0) {
|
if (bitRate > 0) {
|
||||||
@ -102,17 +98,18 @@ public class DownloadFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
return song.getBitRate() == null ? 160 : song.getBitRate();
|
return song.getBitRate() == null ? 160 : song.getBitRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getActualBitrate() {
|
private int getActualBitrate() {
|
||||||
int br = Util.getMaxBitrate(context);
|
int br = Util.getMaxBitrate(context);
|
||||||
if(br == 0 && song.getTranscodedSuffix() != null && "mp3".equals(song.getTranscodedSuffix().toLowerCase())) {
|
if (br == 0 && song.getTranscodedSuffix() != null && "mp3".equals(song.getTranscodedSuffix().toLowerCase())) {
|
||||||
if(song.getBitRate() != null) {
|
if (song.getBitRate() != null) {
|
||||||
br = Math.min(320, song.getBitRate());
|
br = Math.min(320, song.getBitRate());
|
||||||
} else {
|
} else {
|
||||||
br = 320;
|
br = 320;
|
||||||
}
|
}
|
||||||
} else if(song.getSuffix() != null && (song.getTranscodedSuffix() == null || song.getSuffix().equals(song.getTranscodedSuffix()))) {
|
} else if (song.getSuffix() != null && (song.getTranscodedSuffix() == null || song.getSuffix().equals(song.getTranscodedSuffix()))) {
|
||||||
// If just downsampling, don't try to upsample (ie: 128 kpbs -> 192 kpbs)
|
// If just downsampling, don't try to upsample (ie: 128 kpbs -> 192 kpbs)
|
||||||
if(song.getBitRate() != null && (br == 0 || br > song.getBitRate())) {
|
if (song.getBitRate() != null && (br == 0 || br > song.getBitRate())) {
|
||||||
br = song.getBitRate();
|
br = song.getBitRate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,29 +121,16 @@ public class DownloadFile implements BufferFile {
|
|||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrentSize() {
|
|
||||||
if(partialFile.exists()) {
|
|
||||||
return partialFile.length();
|
|
||||||
} else {
|
|
||||||
File file = getCompleteFile();
|
|
||||||
if(file.exists()) {
|
|
||||||
return file.length();
|
|
||||||
} else {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getEstimatedSize() {
|
public long getEstimatedSize() {
|
||||||
if(contentLength != null) {
|
if (contentLength != null) {
|
||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = getCompleteFile();
|
File file = getCompleteFile();
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file.length();
|
return file.length();
|
||||||
} else if(song.getDuration() == null) {
|
} else if (song.getDuration() == null) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
int br = (getBitRate() * 1000) / 8;
|
int br = (getBitRate() * 1000) / 8;
|
||||||
@ -155,29 +139,16 @@ public class DownloadFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getBytesPerSecond() {
|
|
||||||
return currentSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void download() {
|
public synchronized void download() {
|
||||||
rateLimit = false;
|
rateLimit = false;
|
||||||
preDownload();
|
preDownload();
|
||||||
downloadTask.execute();
|
downloadTask.execute();
|
||||||
}
|
}
|
||||||
public synchronized void downloadNow(MusicService musicService) {
|
|
||||||
rateLimit = true;
|
|
||||||
preDownload();
|
|
||||||
downloadTask.setMusicService(musicService);
|
|
||||||
try {
|
|
||||||
downloadTask.doInBackground();
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
// This should never be reached
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void preDownload() {
|
private void preDownload() {
|
||||||
FileUtil.createDirectoryForParent(saveFile);
|
FileUtil.createDirectoryForParent(saveFile);
|
||||||
failedDownload = false;
|
failedDownload = false;
|
||||||
if(!partialFile.exists()) {
|
if (!partialFile.exists()) {
|
||||||
bitRate = getActualBitrate();
|
bitRate = getActualBitrate();
|
||||||
}
|
}
|
||||||
downloadTask = new DownloadTask(context);
|
downloadTask = new DownloadTask(context);
|
||||||
@ -211,9 +182,6 @@ public class DownloadFile implements BufferFile {
|
|||||||
|
|
||||||
return saveFile;
|
return saveFile;
|
||||||
}
|
}
|
||||||
public File getSaveFile() {
|
|
||||||
return saveFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getPartialFile() {
|
public File getPartialFile() {
|
||||||
return partialFile;
|
return partialFile;
|
||||||
@ -244,7 +212,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void onResume() {
|
public synchronized void onResume() {
|
||||||
if(!isWorkDone() && !isFailedMax() && !isDownloading() && !isDownloadCancelled()) {
|
if (!isWorkDone() && !isFailedMax() && !isDownloading() && !isDownloadCancelled()) {
|
||||||
download();
|
download();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,6 +232,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
public boolean isFailed() {
|
public boolean isFailed() {
|
||||||
return failedDownload;
|
return failedDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFailedMax() {
|
public boolean isFailedMax() {
|
||||||
return failed > MAX_FAILURES;
|
return failed > MAX_FAILURES;
|
||||||
}
|
}
|
||||||
@ -317,60 +286,52 @@ public class DownloadFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renamePartial() {
|
||||||
|
Util.renameFile(partialFile, completeFile);
|
||||||
|
saveToStore();
|
||||||
|
}
|
||||||
|
|
||||||
public void setPlaying(boolean isPlaying) {
|
public void setPlaying(boolean isPlaying) {
|
||||||
try {
|
if (saveWhenDone && !isPlaying) {
|
||||||
if(saveWhenDone && !isPlaying) {
|
Util.renameFile(completeFile, saveFile);
|
||||||
Util.renameFile(completeFile, saveFile);
|
renameInStore(completeFile, saveFile);
|
||||||
renameInStore(completeFile, saveFile);
|
saveWhenDone = false;
|
||||||
saveWhenDone = false;
|
} else if (completeWhenDone && !isPlaying) {
|
||||||
} else if(completeWhenDone && !isPlaying) {
|
if (save) {
|
||||||
if(save) {
|
Util.renameFile(partialFile, saveFile);
|
||||||
Util.renameFile(partialFile, saveFile);
|
saveToStore();
|
||||||
saveToStore();
|
} else {
|
||||||
} else {
|
Util.renameFile(partialFile, completeFile);
|
||||||
Util.renameFile(partialFile, completeFile);
|
saveToStore();
|
||||||
saveToStore();
|
|
||||||
}
|
|
||||||
completeWhenDone = false;
|
|
||||||
}
|
}
|
||||||
} catch(IOException ex) {
|
completeWhenDone = false;
|
||||||
Log.w(TAG, "Failed to rename file " + completeFile + " to " + saveFile, ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isPlaying = isPlaying;
|
this.isPlaying = isPlaying;
|
||||||
}
|
}
|
||||||
public void renamePartial() {
|
|
||||||
try {
|
|
||||||
Util.renameFile(partialFile, completeFile);
|
|
||||||
saveToStore();
|
|
||||||
} catch(IOException ex) {
|
|
||||||
Log.w(TAG, "Failed to rename file " + partialFile + " to " + completeFile, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public boolean getPlaying() {
|
|
||||||
return isPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteFromStore() {
|
private void deleteFromStore() {
|
||||||
try {
|
try {
|
||||||
mediaStoreService.deleteFromMediaStore(this);
|
mediaStoreService.deleteFromMediaStore(this);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to remove from store", e);
|
Log.w(TAG, "Failed to remove from store", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveToStore() {
|
private void saveToStore() {
|
||||||
if(!Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HIDE_MEDIA, false)) {
|
if (!Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HIDE_MEDIA, false)) {
|
||||||
try {
|
try {
|
||||||
mediaStoreService.saveInMediaStore(this);
|
mediaStoreService.saveInMediaStore(this);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to save in media store", e);
|
Log.w(TAG, "Failed to save in media store", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renameInStore(File start, File end) {
|
private void renameInStore(File start, File end) {
|
||||||
try {
|
try {
|
||||||
mediaStoreService.renameInMediaStore(start, end);
|
mediaStoreService.renameInMediaStore(start, end);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to rename in store", e);
|
Log.w(TAG, "Failed to rename in store", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,7 +386,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
if (completeFile.exists()) {
|
if (completeFile.exists()) {
|
||||||
if (save) {
|
if (save) {
|
||||||
if(isPlaying) {
|
if (isPlaying) {
|
||||||
saveWhenDone = true;
|
saveWhenDone = true;
|
||||||
} else {
|
} else {
|
||||||
Util.renameFile(completeFile, saveFile);
|
Util.renameFile(completeFile, saveFile);
|
||||||
@ -438,7 +399,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(musicService == null) {
|
if (musicService == null) {
|
||||||
musicService = MusicServiceFactory.getMusicService(context);
|
musicService = MusicServiceFactory.getMusicService(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,15 +407,14 @@ public class DownloadFile implements BufferFile {
|
|||||||
boolean compare;
|
boolean compare;
|
||||||
try {
|
try {
|
||||||
compare = (bitRate == 0) || (song.getDuration() == 0) || (partialFile.length() == 0) || (bitRate * song.getDuration() * 1000 / 8) > partialFile.length();
|
compare = (bitRate == 0) || (song.getDuration() == 0) || (partialFile.length() == 0) || (bitRate * song.getDuration() * 1000 / 8) > partialFile.length();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
compare = true;
|
compare = true;
|
||||||
}
|
}
|
||||||
if(compare) {
|
if (compare) {
|
||||||
// Attempt partial HTTP GET, appending to the file if it exists.
|
// Attempt partial HTTP GET, appending to the file if it exists.
|
||||||
Response response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
|
Response response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
|
||||||
if(response.header("Content-Length") != null) {
|
if (response.header("Content-Length") != null) {
|
||||||
Log.i(TAG, "Content Length: " + contentLength);
|
Log.i(TAG, "Content Length: " + contentLength);
|
||||||
contentLength = contentLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean partial = response.code() == 206;
|
boolean partial = response.code() == 206;
|
||||||
@ -472,17 +432,17 @@ public class DownloadFile implements BufferFile {
|
|||||||
|
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
throw new Exception("Download of '" + song + "' was cancelled");
|
throw new Exception("Download of '" + song + "' was cancelled");
|
||||||
} else if(partialFile.length() == 0) {
|
} else if (partialFile.length() == 0) {
|
||||||
throw new Exception("Download of '" + song + "' failed. File is 0 bytes long.");
|
throw new Exception("Download of '" + song + "' failed. File is 0 bytes long.");
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadAndSaveCoverArt(musicService);
|
downloadAndSaveCoverArt(musicService);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isPlaying) {
|
if (isPlaying) {
|
||||||
completeWhenDone = true;
|
completeWhenDone = true;
|
||||||
} else {
|
} else {
|
||||||
if(save) {
|
if (save) {
|
||||||
Util.renameFile(partialFile, saveFile);
|
Util.renameFile(partialFile, saveFile);
|
||||||
} else {
|
} else {
|
||||||
Util.renameFile(partialFile, completeFile);
|
Util.renameFile(partialFile, completeFile);
|
||||||
@ -490,20 +450,20 @@ public class DownloadFile implements BufferFile {
|
|||||||
DownloadFile.this.saveToStore();
|
DownloadFile.this.saveToStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(InterruptedException x) {
|
} catch (InterruptedException x) {
|
||||||
throw x;
|
throw x;
|
||||||
} catch(FileNotFoundException x) {
|
} catch (FileNotFoundException x) {
|
||||||
Util.delete(completeFile);
|
Util.delete(completeFile);
|
||||||
Util.delete(saveFile);
|
Util.delete(saveFile);
|
||||||
if(!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
failed = MAX_FAILURES + 1;
|
failed = MAX_FAILURES + 1;
|
||||||
failedDownload = true;
|
failedDownload = true;
|
||||||
Log.w(TAG, "Failed to download '" + song + "'.", x);
|
Log.w(TAG, "Failed to download '" + song + "'.", x);
|
||||||
}
|
}
|
||||||
} catch(IOException x) {
|
} catch (IOException x) {
|
||||||
Util.delete(completeFile);
|
Util.delete(completeFile);
|
||||||
Util.delete(saveFile);
|
Util.delete(saveFile);
|
||||||
if(!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
failedDownload = true;
|
failedDownload = true;
|
||||||
Log.w(TAG, "Failed to download '" + song + "'.", x);
|
Log.w(TAG, "Failed to download '" + song + "'.", x);
|
||||||
}
|
}
|
||||||
@ -529,7 +489,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
|
|
||||||
// Only run these if not interrupted, ie: cancelled
|
// Only run these if not interrupted, ie: cancelled
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
if(downloadService != null && !isCancelled()) {
|
if (downloadService != null && !isCancelled()) {
|
||||||
new CacheCleaner(context, downloadService).cleanSpace();
|
new CacheCleaner(context, downloadService).cleanSpace();
|
||||||
checkDownloads();
|
checkDownloads();
|
||||||
}
|
}
|
||||||
@ -539,7 +499,7 @@ public class DownloadFile implements BufferFile {
|
|||||||
|
|
||||||
private void checkDownloads() {
|
private void checkDownloads() {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
if(downloadService != null) {
|
if (downloadService != null) {
|
||||||
downloadService.checkDownloads();
|
downloadService.checkDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,16 +509,12 @@ public class DownloadFile implements BufferFile {
|
|||||||
return "DownloadTask (" + song + ")";
|
return "DownloadTask (" + song + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMusicService(MusicService musicService) {
|
private void downloadAndSaveCoverArt(MusicService musicService) {
|
||||||
this.musicService = musicService;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void downloadAndSaveCoverArt(MusicService musicService) throws Exception {
|
|
||||||
try {
|
try {
|
||||||
if (song.getCoverArt() != null) {
|
if (song.getCoverArt() != null) {
|
||||||
// Check if album art already exists, don't want to needlessly load into memory
|
// Check if album art already exists, don't want to needlessly load into memory
|
||||||
File albumArtFile = FileUtil.getAlbumArtFile(context, song);
|
File albumArtFile = FileUtil.getAlbumArtFile(context, song);
|
||||||
if(!albumArtFile.exists()) {
|
if (!albumArtFile.exists()) {
|
||||||
musicService.getCoverArt(context, song, 0, null, null);
|
musicService.getCoverArt(context, song, 0, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,23 +558,18 @@ public class DownloadFile implements BufferFile {
|
|||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (now - lastLog > 3000L) { // Only every so often.
|
if (now - lastLog > 3000L) { // Only every so often.
|
||||||
Log.i(TAG, "Downloaded " + Util.formatBytes(count) + " of " + song);
|
Log.i(TAG, "Downloaded " + Util.formatBytes(count) + " of " + song);
|
||||||
currentSpeed = lastCount / ((now - lastLog) / 1000L);
|
|
||||||
lastLog = now;
|
lastLog = now;
|
||||||
lastCount = 0;
|
lastCount = 0;
|
||||||
|
|
||||||
// Re-establish every few seconds whether screen is on or not
|
// Re-establish every few seconds whether screen is on or not
|
||||||
if(rateLimit) {
|
if (rateLimit) {
|
||||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||||
if(pm.isScreenOn()) {
|
activeLimit = pm.isScreenOn();
|
||||||
activeLimit = true;
|
|
||||||
} else {
|
|
||||||
activeLimit = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If screen is on and rateLimit is true, stop downloading from exhausting bandwidth
|
// If screen is on and rateLimit is true, stop downloading from exhausting bandwidth
|
||||||
if(activeLimit) {
|
if (activeLimit) {
|
||||||
Thread.sleep(10L);
|
Thread.sleep(10L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -18,12 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -36,64 +30,60 @@ import android.telephony.TelephonyManager;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
import net.nullsum.audinaut.domain.PlayerQueue;
|
||||||
import net.nullsum.audinaut.domain.PlayerState;
|
import net.nullsum.audinaut.domain.PlayerState;
|
||||||
import net.nullsum.audinaut.util.CacheCleaner;
|
import net.nullsum.audinaut.util.CacheCleaner;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
import net.nullsum.audinaut.util.Pair;
|
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.SongDBHandler;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.PlayerState.PREPARING;
|
import static net.nullsum.audinaut.domain.PlayerState.PREPARING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class DownloadServiceLifecycleSupport {
|
public class DownloadServiceLifecycleSupport {
|
||||||
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
|
||||||
public static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser";
|
public static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser";
|
||||||
|
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
||||||
private static final int DEBOUNCE_TIME = 200;
|
private static final int DEBOUNCE_TIME = 200;
|
||||||
|
|
||||||
private final DownloadService downloadService;
|
private final DownloadService downloadService;
|
||||||
|
private final AtomicBoolean setup = new AtomicBoolean(false);
|
||||||
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
private Looper eventLooper;
|
private Looper eventLooper;
|
||||||
private Handler eventHandler;
|
private Handler eventHandler;
|
||||||
private BroadcastReceiver ejectEventReceiver;
|
private BroadcastReceiver ejectEventReceiver;
|
||||||
private PhoneStateListener phoneStateListener;
|
private PhoneStateListener phoneStateListener;
|
||||||
private boolean externalStorageAvailable= true;
|
private boolean externalStorageAvailable = true;
|
||||||
private ReentrantLock lock = new ReentrantLock();
|
|
||||||
private final AtomicBoolean setup = new AtomicBoolean(false);
|
|
||||||
private long lastPressTime = 0;
|
private long lastPressTime = 0;
|
||||||
private SilentBackgroundTask<Void> currentSavePlayQueueTask = null;
|
|
||||||
private Date lastChange = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This receiver manages the intent that could come from other applications.
|
* This receiver manages the intent that could come from other applications.
|
||||||
*/
|
*/
|
||||||
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver intentReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(() -> {
|
||||||
@Override
|
String action = intent.getAction();
|
||||||
public void run() {
|
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
||||||
String action = intent.getAction();
|
if (DownloadService.CMD_PLAY.equals(action)) {
|
||||||
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
downloadService.play();
|
||||||
if (DownloadService.CMD_PLAY.equals(action)) {
|
} else if (DownloadService.CMD_NEXT.equals(action)) {
|
||||||
downloadService.play();
|
downloadService.next();
|
||||||
} else if (DownloadService.CMD_NEXT.equals(action)) {
|
} else if (DownloadService.CMD_PREVIOUS.equals(action)) {
|
||||||
downloadService.next();
|
downloadService.previous();
|
||||||
} else if (DownloadService.CMD_PREVIOUS.equals(action)) {
|
} else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
||||||
downloadService.previous();
|
downloadService.togglePlayPause();
|
||||||
} else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
} else if (DownloadService.CMD_PAUSE.equals(action)) {
|
||||||
downloadService.togglePlayPause();
|
downloadService.pause();
|
||||||
} else if (DownloadService.CMD_PAUSE.equals(action)) {
|
} else if (DownloadService.CMD_STOP.equals(action)) {
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
} else if (DownloadService.CMD_STOP.equals(action)) {
|
downloadService.seekTo(0);
|
||||||
downloadService.pause();
|
|
||||||
downloadService.seekTo(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -105,30 +95,27 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
new Thread(new Runnable() {
|
new Thread(() -> {
|
||||||
@Override
|
Looper.prepare();
|
||||||
public void run() {
|
eventLooper = Looper.myLooper();
|
||||||
Looper.prepare();
|
eventHandler = new Handler(eventLooper);
|
||||||
eventLooper = Looper.myLooper();
|
|
||||||
eventHandler = new Handler(eventLooper);
|
|
||||||
|
|
||||||
// Deserialize queue before starting looper
|
// Deserialize queue before starting looper
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
deserializeDownloadQueueNow();
|
deserializeDownloadQueueNow();
|
||||||
|
|
||||||
// Wait until PREPARING is done to mark lifecycle as ready to receive events
|
// Wait until PREPARING is done to mark lifecycle as ready to receive events
|
||||||
while(downloadService.getPlayerState() == PREPARING) {
|
while (downloadService.getPlayerState() == PREPARING) {
|
||||||
Util.sleepQuietly(50L);
|
Util.sleepQuietly(50L);
|
||||||
}
|
|
||||||
|
|
||||||
setup.set(true);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Looper.loop();
|
setup.set(true);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Looper.loop();
|
||||||
}, "DownloadServiceLifecycleSupport").start();
|
}, "DownloadServiceLifecycleSupport").start();
|
||||||
|
|
||||||
// Stop when SD card is ejected.
|
// Stop when SD card is ejected.
|
||||||
@ -181,70 +168,67 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
|
|
||||||
if(eventHandler == null) {
|
if (eventHandler == null) {
|
||||||
Util.sleepQuietly(100L);
|
Util.sleepQuietly(100L);
|
||||||
}
|
}
|
||||||
if(eventHandler == null) {
|
if (eventHandler == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(() -> {
|
||||||
@Override
|
if (!setup.get()) {
|
||||||
public void run() {
|
lock.lock();
|
||||||
if(!setup.get()) {
|
lock.unlock();
|
||||||
lock.lock();
|
}
|
||||||
lock.unlock();
|
|
||||||
|
if (DownloadService.START_PLAY.equals(action)) {
|
||||||
|
int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
||||||
|
if (offlinePref != 0) {
|
||||||
|
boolean offline = (offlinePref == 2);
|
||||||
|
Util.setOffline(downloadService, offline);
|
||||||
|
if (offline) {
|
||||||
|
downloadService.clearIncomplete();
|
||||||
|
} else {
|
||||||
|
downloadService.checkDownloads();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DownloadService.START_PLAY.equals(action)) {
|
if (intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) {
|
||||||
int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
// Add shuffle parameters
|
||||||
if(offlinePref != 0) {
|
SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit();
|
||||||
boolean offline = (offlinePref == 2);
|
String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR);
|
||||||
Util.setOffline(downloadService, offline);
|
if (startYear != null) {
|
||||||
if (offline) {
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
|
||||||
downloadService.clearIncomplete();
|
|
||||||
} else {
|
|
||||||
downloadService.checkDownloads();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) {
|
String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR);
|
||||||
// Add shuffle parameters
|
if (endYear != null) {
|
||||||
SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit();
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
|
||||||
String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR);
|
|
||||||
if(startYear != null) {
|
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
|
|
||||||
}
|
|
||||||
|
|
||||||
String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR);
|
|
||||||
if(endYear != null) {
|
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
|
|
||||||
}
|
|
||||||
|
|
||||||
String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE);
|
|
||||||
if(genre != null) {
|
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
|
||||||
}
|
|
||||||
editor.apply();
|
|
||||||
|
|
||||||
downloadService.clear();
|
|
||||||
downloadService.setShufflePlayEnabled(true);
|
|
||||||
} else {
|
|
||||||
downloadService.start();
|
|
||||||
}
|
}
|
||||||
} else if(DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
|
||||||
downloadService.togglePlayPause();
|
String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE);
|
||||||
} else if(DownloadService.CMD_NEXT.equals(action)) {
|
if (genre != null) {
|
||||||
downloadService.next();
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
||||||
} else if(DownloadService.CMD_PREVIOUS.equals(action)) {
|
|
||||||
downloadService.previous();
|
|
||||||
} else if(DownloadService.CANCEL_DOWNLOADS.equals(action)) {
|
|
||||||
downloadService.clearBackground();
|
|
||||||
} else if(intent.getExtras() != null) {
|
|
||||||
final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
|
||||||
if (event != null) {
|
|
||||||
handleKeyEvent(event);
|
|
||||||
}
|
}
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
downloadService.clear();
|
||||||
|
downloadService.setShufflePlayEnabled(true);
|
||||||
|
} else {
|
||||||
|
downloadService.start();
|
||||||
|
}
|
||||||
|
} else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
||||||
|
downloadService.togglePlayPause();
|
||||||
|
} else if (DownloadService.CMD_NEXT.equals(action)) {
|
||||||
|
downloadService.next();
|
||||||
|
} else if (DownloadService.CMD_PREVIOUS.equals(action)) {
|
||||||
|
downloadService.previous();
|
||||||
|
} else if (DownloadService.CANCEL_DOWNLOADS.equals(action)) {
|
||||||
|
downloadService.clearBackground();
|
||||||
|
} else if (intent.getExtras() != null) {
|
||||||
|
final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||||
|
if (event != null) {
|
||||||
|
handleKeyEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -266,29 +250,23 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void serializeDownloadQueue() {
|
public void serializeDownloadQueue() {
|
||||||
serializeDownloadQueue(true);
|
if (!setup.get()) {
|
||||||
}
|
|
||||||
public void serializeDownloadQueue(final boolean serializeRemote) {
|
|
||||||
if(!setup.get()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<DownloadFile> songs = new ArrayList<DownloadFile>(downloadService.getSongs());
|
final List<DownloadFile> songs = new ArrayList<>(downloadService.getSongs());
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(() -> {
|
||||||
@Override
|
if (lock.tryLock()) {
|
||||||
public void run() {
|
try {
|
||||||
if(lock.tryLock()) {
|
serializeDownloadQueueNow(songs);
|
||||||
try {
|
} finally {
|
||||||
serializeDownloadQueueNow(songs, serializeRemote);
|
lock.unlock();
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serializeDownloadQueueNow(List<DownloadFile> songs, boolean serializeRemote) {
|
private void serializeDownloadQueueNow(List<DownloadFile> songs) {
|
||||||
final PlayerQueue state = new PlayerQueue();
|
final PlayerQueue state = new PlayerQueue();
|
||||||
for (DownloadFile downloadFile : songs) {
|
for (DownloadFile downloadFile : songs) {
|
||||||
state.songs.add(downloadFile.getSong());
|
state.songs.add(downloadFile.getSong());
|
||||||
@ -300,11 +278,9 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
state.currentPlayingPosition = downloadService.getPlayerPosition();
|
state.currentPlayingPosition = downloadService.getPlayerPosition();
|
||||||
|
|
||||||
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
||||||
if(currentPlaying != null) {
|
if (currentPlaying != null) {
|
||||||
state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable();
|
state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable();
|
||||||
}
|
}
|
||||||
state.changed = lastChange = new Date();
|
|
||||||
|
|
||||||
Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||||
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
|
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
|
||||||
}
|
}
|
||||||
@ -321,24 +297,16 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||||
|
|
||||||
// Rename first thing before anything else starts
|
// Rename first thing before anything else starts
|
||||||
if(state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) {
|
if (state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) {
|
||||||
DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false);
|
DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false);
|
||||||
currentPlaying.renamePartial();
|
currentPlaying.renamePartial();
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadService.restore(state.songs, state.toDelete, state.currentPlayingIndex, state.currentPlayingPosition);
|
downloadService.restore(state.songs, state.toDelete, state.currentPlayingIndex, state.currentPlayingPosition);
|
||||||
|
|
||||||
if(state != null) {
|
|
||||||
lastChange = state.changed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getLastChange() {
|
private void handleKeyEvent(KeyEvent event) {
|
||||||
return lastChange;
|
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) {
|
||||||
}
|
|
||||||
|
|
||||||
public void handleKeyEvent(KeyEvent event) {
|
|
||||||
if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) {
|
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
downloadService.fastForward();
|
downloadService.fastForward();
|
||||||
@ -347,25 +315,25 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
downloadService.rewind();
|
downloadService.rewind();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(event.getAction() == KeyEvent.ACTION_UP) {
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - 500)) {
|
if (lastPressTime < (System.currentTimeMillis() - 500)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.togglePlayPause();
|
downloadService.togglePlayPause();
|
||||||
} else {
|
} else {
|
||||||
downloadService.next(false, true);
|
downloadService.next(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
if (lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.previous();
|
downloadService.previous();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
if (lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
}
|
}
|
||||||
@ -380,7 +348,7 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
downloadService.stop();
|
downloadService.stop();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
if(downloadService.getPlayerState() != PlayerState.STARTED) {
|
if (downloadService.getPlayerState() != PlayerState.STARTED) {
|
||||||
downloadService.start();
|
downloadService.start();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -401,28 +369,25 @@ public class DownloadServiceLifecycleSupport {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(final int state, String incomingNumber) {
|
public void onCallStateChanged(final int state, String incomingNumber) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(() -> {
|
||||||
@Override
|
switch (state) {
|
||||||
public void run() {
|
case TelephonyManager.CALL_STATE_RINGING:
|
||||||
switch (state) {
|
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||||
case TelephonyManager.CALL_STATE_RINGING:
|
if (downloadService.getPlayerState() == PlayerState.STARTED) {
|
||||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
resumeAfterCall = true;
|
||||||
if (downloadService.getPlayerState() == PlayerState.STARTED) {
|
downloadService.pause(true);
|
||||||
resumeAfterCall = true;
|
}
|
||||||
downloadService.pause(true);
|
break;
|
||||||
|
case TelephonyManager.CALL_STATE_IDLE:
|
||||||
|
if (resumeAfterCall) {
|
||||||
|
resumeAfterCall = false;
|
||||||
|
if (downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) {
|
||||||
|
downloadService.start();
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case TelephonyManager.CALL_STATE_IDLE:
|
break;
|
||||||
if (resumeAfterCall) {
|
default:
|
||||||
resumeAfterCall = false;
|
break;
|
||||||
if(downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) {
|
|
||||||
downloadService.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class HeadphoneListenerService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
if(!Util.shouldStartOnHeadphones(this)) {
|
if (!Util.shouldStartOnHeadphones(this)) {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,10 +56,10 @@ public class HeadphoneListenerService extends Service {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(receiver != null) {
|
if (receiver != null) {
|
||||||
unregisterReceiver(receiver);
|
unregisterReceiver(receiver);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -27,9 +25,11 @@ import android.database.Cursor;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
@ -67,7 +67,7 @@ public class MediaStoreService {
|
|||||||
if (song.getYear() != null) {
|
if (song.getYear() != null) {
|
||||||
values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear());
|
values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear());
|
||||||
}
|
}
|
||||||
if(song.getTranscodedContentType() != null) {
|
if (song.getTranscodedContentType() != null) {
|
||||||
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getTranscodedContentType());
|
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getTranscodedContentType());
|
||||||
} else {
|
} else {
|
||||||
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType());
|
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType());
|
||||||
|
@ -18,24 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.domain.Indexes;
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.domain.SearchCritera;
|
import net.nullsum.audinaut.domain.SearchCritera;
|
||||||
import net.nullsum.audinaut.domain.SearchResult;
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
import net.nullsum.audinaut.domain.User;
|
import net.nullsum.audinaut.domain.User;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
@ -78,7 +77,6 @@ public interface MusicService {
|
|||||||
|
|
||||||
MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
|
||||||
MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
||||||
@ -91,11 +89,5 @@ public interface MusicService {
|
|||||||
|
|
||||||
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
|
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
|
||||||
|
|
||||||
void savePlayQueue(List<MusicDirectory.Entry> songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception;
|
|
||||||
|
|
||||||
PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception;
|
|
||||||
|
|
||||||
void setInstance(Integer instance) throws Exception;
|
void setInstance(Integer instance) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ package net.nullsum.audinaut.service;
|
|||||||
*/
|
*/
|
||||||
public class OfflineException extends Exception {
|
public class OfflineException extends Exception {
|
||||||
|
|
||||||
public OfflineException(String message) {
|
public OfflineException() {
|
||||||
super(message);
|
super(OfflineMusicService.ERRORMSG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,30 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.domain.Indexes;
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
|
import net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.domain.SearchCritera;
|
import net.nullsum.audinaut.domain.SearchCritera;
|
||||||
@ -49,21 +34,31 @@ import net.nullsum.audinaut.domain.SearchResult;
|
|||||||
import net.nullsum.audinaut.domain.User;
|
import net.nullsum.audinaut.domain.User;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
import net.nullsum.audinaut.util.Pair;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.SongDBHandler;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
import java.io.*;
|
|
||||||
import java.util.Comparator;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class OfflineMusicService implements MusicService {
|
public class OfflineMusicService implements MusicService {
|
||||||
|
public static final String ERRORMSG = "Not available in offline mode";
|
||||||
private static final String TAG = OfflineMusicService.class.getSimpleName();
|
private static final String TAG = OfflineMusicService.class.getSimpleName();
|
||||||
private static final String ERRORMSG = "Not available in offline mode";
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -73,7 +68,7 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
for (File file : FileUtil.listFiles(root)) {
|
for (File file : FileUtil.listFiles(root)) {
|
||||||
@ -83,31 +78,31 @@ public class OfflineMusicService implements MusicService {
|
|||||||
artist.setIndex(file.getName().substring(0, 1));
|
artist.setIndex(file.getName().substring(0, 1));
|
||||||
artist.setName(file.getName());
|
artist.setName(file.getName());
|
||||||
artists.add(artist);
|
artists.add(artist);
|
||||||
} else if(!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) {
|
} else if (!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) {
|
||||||
entries.add(createEntry(context, file));
|
entries.add(createEntry(context, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Indexes indexes = new Indexes(0L, Collections.<Artist>emptyList(), artists, entries);
|
return new Indexes(Collections.emptyList(), artists, entries);
|
||||||
return indexes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
return getMusicDirectory(id, artistName, refresh, context, progressListener, false);
|
return getMusicDirectory(id, context);
|
||||||
}
|
}
|
||||||
private MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener, boolean isPodcast) throws Exception {
|
|
||||||
|
private MusicDirectory getMusicDirectory(String id, Context context) throws Exception {
|
||||||
File dir = new File(id);
|
File dir = new File(id);
|
||||||
MusicDirectory result = new MusicDirectory();
|
MusicDirectory result = new MusicDirectory();
|
||||||
result.setName(dir.getName());
|
result.setName(dir.getName());
|
||||||
|
|
||||||
Set<String> names = new HashSet<String>();
|
Set<String> names = new HashSet<>();
|
||||||
|
|
||||||
for (File file : FileUtil.listMediaFiles(dir)) {
|
for (File file : FileUtil.listMediaFiles(dir)) {
|
||||||
String name = getName(file);
|
String name = getName(file);
|
||||||
if (name != null & !names.contains(name)) {
|
if (name != null & !names.contains(name)) {
|
||||||
names.add(name);
|
names.add(name);
|
||||||
result.addChild(createEntry(context, file, name, true, isPodcast));
|
result.addChild(createEntry(context, file, name, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
result.sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
||||||
@ -116,12 +111,12 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getName(File file) {
|
private String getName(File file) {
|
||||||
@ -141,29 +136,24 @@ public class OfflineMusicService implements MusicService {
|
|||||||
private Entry createEntry(Context context, File file) {
|
private Entry createEntry(Context context, File file) {
|
||||||
return createEntry(context, file, getName(file));
|
return createEntry(context, file, getName(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entry createEntry(Context context, File file, String name) {
|
private Entry createEntry(Context context, File file, String name) {
|
||||||
return createEntry(context, file, name, true);
|
return createEntry(context, file, name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entry createEntry(Context context, File file, String name, boolean load) {
|
private Entry createEntry(Context context, File file, String name, boolean load) {
|
||||||
return createEntry(context, file, name, load, false);
|
|
||||||
}
|
|
||||||
private Entry createEntry(Context context, File file, String name, boolean load, boolean isPodcast) {
|
|
||||||
Entry entry;
|
Entry entry;
|
||||||
entry = new Entry();
|
entry = new Entry();
|
||||||
entry.setDirectory(file.isDirectory());
|
entry.setDirectory(file.isDirectory());
|
||||||
entry.setId(file.getPath());
|
entry.setId(file.getPath());
|
||||||
entry.setParent(file.getParent());
|
entry.setParent(file.getParent());
|
||||||
entry.setSize(file.length());
|
|
||||||
String root = FileUtil.getMusicDirectory(context).getPath();
|
String root = FileUtil.getMusicDirectory(context).getPath();
|
||||||
if(!file.getParentFile().getParentFile().getPath().equals(root)) {
|
entry.setPath(file.getPath().replaceFirst("^" + root + "/", ""));
|
||||||
entry.setGrandParent(file.getParentFile().getParent());
|
|
||||||
}
|
|
||||||
entry.setPath(file.getPath().replaceFirst("^" + root + "/" , ""));
|
|
||||||
String title = name;
|
String title = name;
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
File artistFolder = file.getParentFile().getParentFile();
|
File artistFolder = file.getParentFile().getParentFile();
|
||||||
File albumFolder = file.getParentFile();
|
File albumFolder = file.getParentFile();
|
||||||
if(artistFolder.getPath().equals(root)) {
|
if (artistFolder.getPath().equals(root)) {
|
||||||
entry.setArtist(albumFolder.getName());
|
entry.setArtist(albumFolder.getName());
|
||||||
} else {
|
} else {
|
||||||
entry.setArtist(artistFolder.getName());
|
entry.setArtist(artistFolder.getName());
|
||||||
@ -171,16 +161,16 @@ public class OfflineMusicService implements MusicService {
|
|||||||
entry.setAlbum(albumFolder.getName());
|
entry.setAlbum(albumFolder.getName());
|
||||||
|
|
||||||
int index = name.indexOf('-');
|
int index = name.indexOf('-');
|
||||||
if(index != -1) {
|
if (index != -1) {
|
||||||
try {
|
try {
|
||||||
entry.setTrack(Integer.parseInt(name.substring(0, index)));
|
entry.setTrack(Integer.parseInt(name.substring(0, index)));
|
||||||
title = title.substring(index + 1);
|
title = title.substring(index + 1);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Failed parseInt, just means track filled out
|
// Failed parseInt, just means track filled out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(load) {
|
if (load) {
|
||||||
entry.loadMetadata(file);
|
entry.loadMetadata(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,32 +189,32 @@ public class OfflineMusicService implements MusicService {
|
|||||||
public Bitmap getCoverArt(Context context, Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
public Bitmap getCoverArt(Context context, Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
||||||
try {
|
try {
|
||||||
return FileUtil.getAlbumArtBitmap(context, entry, size);
|
return FileUtil.getAlbumArtBitmap(context, entry, size);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response getDownloadInputStream(Context context, Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
public Response getDownloadInputStream(Context context, Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
|
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
List<Entry> albums = new ArrayList<Entry>();
|
List<Entry> albums = new ArrayList<>();
|
||||||
List<Entry> songs = new ArrayList<Entry>();
|
List<Entry> songs = new ArrayList<>();
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
int closeness = 0;
|
int closeness;
|
||||||
for (File artistFile : FileUtil.listFiles(root)) {
|
for (File artistFile : FileUtil.listFiles(root)) {
|
||||||
String artistName = artistFile.getName();
|
String artistName = artistFile.getName();
|
||||||
if (artistFile.isDirectory()) {
|
if (artistFile.isDirectory()) {
|
||||||
if((closeness = matchCriteria(criteria, artistName)) > 0) {
|
if ((closeness = matchCriteria(criteria, artistName)) > 0) {
|
||||||
Artist artist = new Artist();
|
Artist artist = new Artist();
|
||||||
artist.setId(artistFile.getPath());
|
artist.setId(artistFile.getPath());
|
||||||
artist.setIndex(artistFile.getName().substring(0, 1));
|
artist.setIndex(artistFile.getName().substring(0, 1));
|
||||||
@ -237,43 +227,31 @@ public class OfflineMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(artists, new Comparator<Artist>() {
|
Collections.sort(artists, (lhs, rhs) -> {
|
||||||
public int compare(Artist lhs, Artist rhs) {
|
if (lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
return 0;
|
||||||
return 0;
|
} else if (lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
}
|
return -1;
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
} else {
|
||||||
return -1;
|
return 1;
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Collections.sort(albums, new Comparator<Entry>() {
|
Collections.sort(albums, (lhs, rhs) -> {
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
if (lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
return 0;
|
||||||
return 0;
|
} else if (lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
}
|
return -1;
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
} else {
|
||||||
return -1;
|
return 1;
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Collections.sort(songs, new Comparator<Entry>() {
|
Collections.sort(songs, (lhs, rhs) -> {
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
if (lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
return 0;
|
||||||
return 0;
|
} else if (lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
}
|
return -1;
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
} else {
|
||||||
return -1;
|
return 1;
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -290,26 +268,25 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<Entry> albums, List<Entry> songs) {
|
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<Entry> albums, List<Entry> songs) {
|
||||||
int closeness;
|
int closeness;
|
||||||
for(File albumFile : FileUtil.listMediaFiles(file)) {
|
for (File albumFile : FileUtil.listMediaFiles(file)) {
|
||||||
if(albumFile.isDirectory()) {
|
if (albumFile.isDirectory()) {
|
||||||
String albumName = getName(albumFile);
|
String albumName = getName(albumFile);
|
||||||
if((closeness = matchCriteria(criteria, albumName)) > 0) {
|
if ((closeness = matchCriteria(criteria, albumName)) > 0) {
|
||||||
Entry album = createEntry(context, albumFile, albumName);
|
Entry album = createEntry(context, albumFile, albumName);
|
||||||
album.setArtist(artistName);
|
album.setArtist(artistName);
|
||||||
album.setCloseness(closeness);
|
album.setCloseness(closeness);
|
||||||
albums.add(album);
|
albums.add(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(File songFile : FileUtil.listMediaFiles(albumFile)) {
|
for (File songFile : FileUtil.listMediaFiles(albumFile)) {
|
||||||
String songName = getName(songFile);
|
String songName = getName(songFile);
|
||||||
if(songName == null) {
|
if (songName == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(songFile.isDirectory()) {
|
if (songFile.isDirectory()) {
|
||||||
recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs);
|
recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs);
|
||||||
}
|
} else if ((closeness = matchCriteria(criteria, songName)) > 0) {
|
||||||
else if((closeness = matchCriteria(criteria, songName)) > 0){
|
|
||||||
Entry song = createEntry(context, albumFile, songName);
|
Entry song = createEntry(context, albumFile, songName);
|
||||||
song.setArtist(artistName);
|
song.setArtist(artistName);
|
||||||
song.setAlbum(albumName);
|
song.setAlbum(albumName);
|
||||||
@ -317,10 +294,9 @@ public class OfflineMusicService implements MusicService {
|
|||||||
songs.add(song);
|
songs.add(song);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
String songName = getName(albumFile);
|
String songName = getName(albumFile);
|
||||||
if((closeness = matchCriteria(criteria, songName)) > 0) {
|
if ((closeness = matchCriteria(criteria, songName)) > 0) {
|
||||||
Entry song = createEntry(context, albumFile, songName);
|
Entry song = createEntry(context, albumFile, songName);
|
||||||
song.setArtist(artistName);
|
song.setArtist(artistName);
|
||||||
song.setAlbum(songName);
|
song.setAlbum(songName);
|
||||||
@ -330,11 +306,12 @@ public class OfflineMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int matchCriteria(SearchCritera criteria, String name) {
|
private int matchCriteria(SearchCritera criteria, String name) {
|
||||||
if (criteria.getPattern().matcher(name).matches()) {
|
if (criteria.getPattern().matcher(name).matches()) {
|
||||||
return Util.getStringDistance(
|
return Util.getStringDistance(
|
||||||
criteria.getQuery().toLowerCase(),
|
criteria.getQuery().toLowerCase(),
|
||||||
name.toLowerCase());
|
name.toLowerCase());
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -342,16 +319,16 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Playlist> playlists = new ArrayList<Playlist>();
|
List<Playlist> playlists = new ArrayList<>();
|
||||||
File root = FileUtil.getPlaylistDirectory(context);
|
File root = FileUtil.getPlaylistDirectory(context);
|
||||||
String lastServer = null;
|
String lastServer = null;
|
||||||
boolean removeServer = true;
|
boolean removeServer = true;
|
||||||
for (File folder : FileUtil.listFiles(root)) {
|
for (File folder : FileUtil.listFiles(root)) {
|
||||||
if(folder.isDirectory()) {
|
if (folder.isDirectory()) {
|
||||||
String server = folder.getName();
|
String server = folder.getName();
|
||||||
SortedSet<File> fileList = FileUtil.listFiles(folder);
|
SortedSet<File> fileList = FileUtil.listFiles(folder);
|
||||||
for(File file: fileList) {
|
for (File file : fileList) {
|
||||||
if(FileUtil.isPlaylistFile(file)) {
|
if (FileUtil.isPlaylistFile(file)) {
|
||||||
String id = file.getName();
|
String id = file.getName();
|
||||||
String filename = FileUtil.getBaseName(id);
|
String filename = FileUtil.getBaseName(id);
|
||||||
String name = server + ": " + filename;
|
String name = server + ": " + filename;
|
||||||
@ -366,41 +343,41 @@ public class OfflineMusicService implements MusicService {
|
|||||||
buffer = new BufferedReader(reader);
|
buffer = new BufferedReader(reader);
|
||||||
|
|
||||||
String line = buffer.readLine();
|
String line = buffer.readLine();
|
||||||
while( (line = buffer.readLine()) != null ){
|
while ((line = buffer.readLine()) != null) {
|
||||||
// No matter what, end file can't have .complete in it
|
// No matter what, end file can't have .complete in it
|
||||||
line = line.replace(".complete", "");
|
line = line.replace(".complete", "");
|
||||||
File entryFile = new File(line);
|
File entryFile = new File(line);
|
||||||
|
|
||||||
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
||||||
File checkFile = entryFile;
|
File checkFile = entryFile;
|
||||||
if(!checkFile.exists()) {
|
if (!checkFile.exists()) {
|
||||||
// If normal file doens't exist, check if .complete version does
|
// If normal file doens't exist, check if .complete version does
|
||||||
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
||||||
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryName = getName(entryFile);
|
String entryName = getName(entryFile);
|
||||||
if(checkFile.exists() && entryName != null){
|
if (checkFile.exists() && entryName != null) {
|
||||||
songCount++;
|
songCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.setSongCount(Integer.toString(songCount));
|
playlist.setSongCount(Integer.toString(songCount));
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to count songs in playlist", e);
|
Log.w(TAG, "Failed to count songs in playlist", e);
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(buffer);
|
Util.close(buffer);
|
||||||
Util.close(reader);
|
Util.close(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(songCount > 0) {
|
if (songCount > 0) {
|
||||||
playlists.add(playlist);
|
playlists.add(playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!server.equals(lastServer) && fileList.size() > 0) {
|
if (!server.equals(lastServer) && fileList.size() > 0) {
|
||||||
if(lastServer != null) {
|
if (lastServer != null) {
|
||||||
removeServer = false;
|
removeServer = false;
|
||||||
}
|
}
|
||||||
lastServer = server;
|
lastServer = server;
|
||||||
@ -409,14 +386,14 @@ public class OfflineMusicService implements MusicService {
|
|||||||
// Delete legacy playlist files
|
// Delete legacy playlist files
|
||||||
try {
|
try {
|
||||||
folder.delete();
|
folder.delete();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to delete old playlist file: " + folder.getName());
|
Log.w(TAG, "Failed to delete old playlist file: " + folder.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(removeServer) {
|
if (removeServer) {
|
||||||
for(Playlist playlist: playlists) {
|
for (Playlist playlist : playlists) {
|
||||||
playlist.setName(playlist.getName().substring(playlist.getId().length() + 2));
|
playlist.setName(playlist.getName().substring(playlist.getId().length() + 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,7 +411,7 @@ public class OfflineMusicService implements MusicService {
|
|||||||
BufferedReader buffer = null;
|
BufferedReader buffer = null;
|
||||||
try {
|
try {
|
||||||
int firstIndex = name.indexOf(id);
|
int firstIndex = name.indexOf(id);
|
||||||
if(firstIndex != -1) {
|
if (firstIndex != -1) {
|
||||||
name = name.substring(id.length() + 2);
|
name = name.substring(id.length() + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,23 +421,23 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
MusicDirectory playlist = new MusicDirectory();
|
MusicDirectory playlist = new MusicDirectory();
|
||||||
String line = buffer.readLine();
|
String line = buffer.readLine();
|
||||||
if(!"#EXTM3U".equals(line)) return playlist;
|
if (!"#EXTM3U".equals(line)) return playlist;
|
||||||
|
|
||||||
while( (line = buffer.readLine()) != null ){
|
while ((line = buffer.readLine()) != null) {
|
||||||
// No matter what, end file can't have .complete in it
|
// No matter what, end file can't have .complete in it
|
||||||
line = line.replace(".complete", "");
|
line = line.replace(".complete", "");
|
||||||
File entryFile = new File(line);
|
File entryFile = new File(line);
|
||||||
|
|
||||||
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
||||||
File checkFile = entryFile;
|
File checkFile = entryFile;
|
||||||
if(!checkFile.exists()) {
|
if (!checkFile.exists()) {
|
||||||
// If normal file doens't exist, check if .complete version does
|
// If normal file doens't exist, check if .complete version does
|
||||||
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
||||||
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryName = getName(entryFile);
|
String entryName = getName(entryFile);
|
||||||
if(checkFile.exists() && entryName != null){
|
if (checkFile.exists() && entryName != null) {
|
||||||
playlist.addChild(createEntry(context, entryFile, entryName, false));
|
playlist.addChild(createEntry(context, entryFile, entryName, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,68 +451,63 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createPlaylist(String id, String name, List<Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
public void createPlaylist(String id, String name, List<Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToPlaylist(String id, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void addToPlaylist(String id, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void overwritePlaylist(String id, String name, int toRemove, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void overwritePlaylist(String id, String name, int toRemove, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
List<File> children = new LinkedList<File>();
|
List<File> children = new LinkedList<>();
|
||||||
listFilesRecursively(root, children);
|
listFilesRecursively(root, children);
|
||||||
MusicDirectory result = new MusicDirectory();
|
MusicDirectory result = new MusicDirectory();
|
||||||
|
|
||||||
@ -552,27 +524,12 @@ public class OfflineMusicService implements MusicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
public void setInstance(Integer instance) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void savePlayQueue(List<Entry> songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setInstance(Integer instance) throws Exception{
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listFilesRecursively(File parent, List<File> children) {
|
private void listFilesRecursively(File parent, List<File> children) {
|
||||||
|
@ -18,28 +18,19 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import okhttp3.FormBody;
|
|
||||||
import okhttp3.FormBody.Builder;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Credentials;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.domain.*;
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
|
import net.nullsum.audinaut.domain.SearchCritera;
|
||||||
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
|
import net.nullsum.audinaut.domain.User;
|
||||||
import net.nullsum.audinaut.fragments.MainFragment;
|
import net.nullsum.audinaut.fragments.MainFragment;
|
||||||
import net.nullsum.audinaut.service.parser.EntryListParser;
|
import net.nullsum.audinaut.service.parser.EntryListParser;
|
||||||
import net.nullsum.audinaut.service.parser.ErrorParser;
|
import net.nullsum.audinaut.service.parser.ErrorParser;
|
||||||
@ -47,29 +38,39 @@ import net.nullsum.audinaut.service.parser.GenreParser;
|
|||||||
import net.nullsum.audinaut.service.parser.IndexesParser;
|
import net.nullsum.audinaut.service.parser.IndexesParser;
|
||||||
import net.nullsum.audinaut.service.parser.MusicDirectoryParser;
|
import net.nullsum.audinaut.service.parser.MusicDirectoryParser;
|
||||||
import net.nullsum.audinaut.service.parser.MusicFoldersParser;
|
import net.nullsum.audinaut.service.parser.MusicFoldersParser;
|
||||||
import net.nullsum.audinaut.service.parser.PlayQueueParser;
|
|
||||||
import net.nullsum.audinaut.service.parser.PlaylistParser;
|
import net.nullsum.audinaut.service.parser.PlaylistParser;
|
||||||
import net.nullsum.audinaut.service.parser.PlaylistsParser;
|
import net.nullsum.audinaut.service.parser.PlaylistsParser;
|
||||||
import net.nullsum.audinaut.service.parser.RandomSongsParser;
|
import net.nullsum.audinaut.service.parser.RandomSongsParser;
|
||||||
import net.nullsum.audinaut.service.parser.SearchResult2Parser;
|
import net.nullsum.audinaut.service.parser.SearchResult2Parser;
|
||||||
import net.nullsum.audinaut.service.parser.UserParser;
|
import net.nullsum.audinaut.service.parser.UserParser;
|
||||||
import net.nullsum.audinaut.util.BackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.Pair;
|
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.FileUtil;
|
import net.nullsum.audinaut.util.FileUtil;
|
||||||
|
import net.nullsum.audinaut.util.Pair;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.SongDBHandler;
|
import net.nullsum.audinaut.util.SongDBHandler;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
import okhttp3.FormBody.Builder;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class RESTMusicService implements MusicService {
|
public class RESTMusicService implements MusicService {
|
||||||
|
|
||||||
private static OkHttpClient client = new OkHttpClient();
|
|
||||||
private static final String TAG = RESTMusicService.class.getSimpleName();
|
private static final String TAG = RESTMusicService.class.getSimpleName();
|
||||||
|
private static final OkHttpClient client = new OkHttpClient();
|
||||||
private Integer instance;
|
private Integer instance;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -77,8 +78,8 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "ping");
|
String url = getRestUrl(context, "ping");
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -89,11 +90,11 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getMusicFolders");
|
String url = getRestUrl(context, "getMusicFolders");
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new MusicFoldersParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new MusicFoldersParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "getArtists");
|
String url = getRestUrl(context, "getArtists");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
|
|
||||||
if (musicFolderId != null) {
|
if (musicFolderId != null) {
|
||||||
builder.add("musicFolderId", musicFolderId);
|
builder.add("musicFolderId", musicFolderId);
|
||||||
@ -110,9 +111,9 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new IndexesParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new IndexesParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
||||||
@ -123,22 +124,22 @@ public class RESTMusicService implements MusicService {
|
|||||||
public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
if(cacheLocn != null && id.indexOf(cacheLocn) != -1) {
|
if (cacheLocn != null && id.contains(cacheLocn)) {
|
||||||
String search = Util.parseOfflineIDSearch(context, id, cacheLocn);
|
String search = Util.parseOfflineIDSearch(id, cacheLocn);
|
||||||
SearchCritera critera = new SearchCritera(search, 1, 1, 0);
|
SearchCritera critera = new SearchCritera(search, 1, 1, 0);
|
||||||
SearchResult result = search(critera, context, progressListener);
|
SearchResult result = search(critera, context, progressListener);
|
||||||
if(result.getArtists().size() == 1) {
|
if (result.getArtists().size() == 1) {
|
||||||
id = result.getArtists().get(0).getId();
|
id = result.getArtists().get(0).getId();
|
||||||
} else if(result.getAlbums().size() == 1) {
|
} else if (result.getAlbums().size() == 1) {
|
||||||
id = result.getAlbums().get(0).getId();
|
id = result.getAlbums().get(0).getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicDirectory dir = null;
|
MusicDirectory dir = null;
|
||||||
int index, start = 0;
|
int index, start = 0;
|
||||||
while((index = id.indexOf(';', start)) != -1) {
|
while ((index = id.indexOf(';', start)) != -1) {
|
||||||
MusicDirectory extra = getMusicDirectoryImpl(id.substring(start, index), name, refresh, context, progressListener);
|
MusicDirectory extra = getMusicDirectoryImpl(id.substring(start, index), name, context);
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = extra;
|
dir = extra;
|
||||||
} else {
|
} else {
|
||||||
dir.addChildren(extra.getChildren());
|
dir.addChildren(extra.getChildren());
|
||||||
@ -146,8 +147,8 @@ public class RESTMusicService implements MusicService {
|
|||||||
|
|
||||||
start = index + 1;
|
start = index + 1;
|
||||||
}
|
}
|
||||||
MusicDirectory extra = getMusicDirectoryImpl(id.substring(start), name, refresh, context, progressListener);
|
MusicDirectory extra = getMusicDirectoryImpl(id.substring(start), name, context);
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
dir = extra;
|
dir = extra;
|
||||||
} else {
|
} else {
|
||||||
dir.addChildren(extra.getChildren());
|
dir.addChildren(extra.getChildren());
|
||||||
@ -156,20 +157,20 @@ public class RESTMusicService implements MusicService {
|
|||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MusicDirectory getMusicDirectoryImpl(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
private MusicDirectory getMusicDirectoryImpl(String id, String name, Context context) throws Exception {
|
||||||
String url = getRestUrl(context, "getMusicDirectory");
|
String url = getRestUrl(context, "getMusicDirectory");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener);
|
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,16 +179,16 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getArtist");
|
String url = getRestUrl(context, "getArtist");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener);
|
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,16 +197,16 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getAlbum");
|
String url = getRestUrl(context, "getAlbum");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener);
|
return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +214,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
|
public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "search3");
|
String url = getRestUrl(context, "search3");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
|
|
||||||
builder.add("query", critera.getQuery());
|
builder.add("query", critera.getQuery());
|
||||||
builder.add("artistCount", Integer.toString(critera.getArtistCount()));
|
builder.add("artistCount", Integer.toString(critera.getArtistCount()));
|
||||||
@ -223,12 +224,12 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new SearchResult2Parser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new SearchResult2Parser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,16 +238,16 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getPlaylist");
|
String url = getRestUrl(context, "getPlaylist");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new PlaylistParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new PlaylistParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,11 +256,11 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getPlaylists");
|
String url = getRestUrl(context, "getPlaylists");
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new PlaylistsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new PlaylistsParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +268,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "createPlaylist");
|
String url = getRestUrl(context, "createPlaylist");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
builder.add("playlistId", id);
|
builder.add("playlistId", id);
|
||||||
@ -284,9 +285,9 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -298,13 +299,13 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "deletePlaylist");
|
String url = getRestUrl(context, "deletePlaylist");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -315,18 +316,18 @@ public class RESTMusicService implements MusicService {
|
|||||||
public void addToPlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void addToPlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "updatePlaylist");
|
String url = getRestUrl(context, "updatePlaylist");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("playlistId", id);
|
builder.add("playlistId", id);
|
||||||
for(MusicDirectory.Entry song: toAdd) {
|
for (MusicDirectory.Entry song : toAdd) {
|
||||||
builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener));
|
builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -337,19 +338,19 @@ public class RESTMusicService implements MusicService {
|
|||||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "updatePlaylist");
|
String url = getRestUrl(context, "updatePlaylist");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("playlistId", id);
|
builder.add("playlistId", id);
|
||||||
|
|
||||||
for(Integer song: toRemove) {
|
for (Integer song : toRemove) {
|
||||||
builder.add("songIndexToRemove", Integer.toString(song));
|
builder.add("songIndexToRemove", Integer.toString(song));
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -360,24 +361,24 @@ public class RESTMusicService implements MusicService {
|
|||||||
public void overwritePlaylist(String id, String name, int toRemove, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void overwritePlaylist(String id, String name, int toRemove, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "updatePlaylist");
|
String url = getRestUrl(context, "updatePlaylist");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("playlistId", id);
|
builder.add("playlistId", id);
|
||||||
builder.add("name", name);
|
builder.add("name", name);
|
||||||
|
|
||||||
for(MusicDirectory.Entry song: toAdd) {
|
for (MusicDirectory.Entry song : toAdd) {
|
||||||
builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener));
|
builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < toRemove; i++) {
|
for (int i = 0; i < toRemove; i++) {
|
||||||
builder.add("songIndexToRemove", Integer.toString(i));
|
builder.add("songIndexToRemove", Integer.toString(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -388,7 +389,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "updatePlaylist");
|
String url = getRestUrl(context, "updatePlaylist");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("playlistId", id);
|
builder.add("playlistId", id);
|
||||||
builder.add("name", name);
|
builder.add("name", name);
|
||||||
builder.add("comment", comment);
|
builder.add("comment", comment);
|
||||||
@ -397,9 +398,9 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
@ -410,16 +411,16 @@ public class RESTMusicService implements MusicService {
|
|||||||
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "getAlbumList2");
|
String url = getRestUrl(context, "getAlbumList2");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("type", type);
|
builder.add("type", type);
|
||||||
builder.add("size", Integer.toString(size));
|
builder.add("size", Integer.toString(size));
|
||||||
builder.add("offset", Integer.toString(offset));
|
builder.add("offset", Integer.toString(offset));
|
||||||
|
|
||||||
// Add folder if it was set and is non null
|
// Add folder if it was set and is non null
|
||||||
int instance = getInstance(context);
|
int instance = getInstance(context);
|
||||||
if(Util.getAlbumListsPerFolder(context, instance)) {
|
if (Util.getAlbumListsPerFolder(context, instance)) {
|
||||||
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
||||||
if(folderId != null) {
|
if (folderId != null) {
|
||||||
builder.add("musicFolderId", folderId);
|
builder.add("musicFolderId", folderId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -427,12 +428,12 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,15 +441,15 @@ public class RESTMusicService implements MusicService {
|
|||||||
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
String url = getRestUrl(context, "getAlbumList2");
|
String url = getRestUrl(context, "getAlbumList2");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("size", Integer.toString(size));
|
builder.add("size", Integer.toString(size));
|
||||||
builder.add("offset", Integer.toString(offset));
|
builder.add("offset", Integer.toString(offset));
|
||||||
|
|
||||||
int instance = getInstance(context);
|
int instance = getInstance(context);
|
||||||
if("genres".equals(type)) {
|
if ("genres".equals(type)) {
|
||||||
builder.add("type", "byGenre");
|
builder.add("type", "byGenre");
|
||||||
builder.add("genre", extra);
|
builder.add("genre", extra);
|
||||||
} else if("years".equals(type)) {
|
} else if ("years".equals(type)) {
|
||||||
int decade = Integer.parseInt(extra);
|
int decade = Integer.parseInt(extra);
|
||||||
|
|
||||||
builder.add("type", "byYear");
|
builder.add("type", "byYear");
|
||||||
@ -457,9 +458,9 @@ public class RESTMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add folder if it was set and is non null
|
// Add folder if it was set and is non null
|
||||||
if(Util.getAlbumListsPerFolder(context, instance)) {
|
if (Util.getAlbumListsPerFolder(context, instance)) {
|
||||||
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
||||||
if(folderId != null) {
|
if (folderId != null) {
|
||||||
builder.add("musicFolderId", folderId);
|
builder.add("musicFolderId", folderId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,23 +468,23 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("size", Integer.toString(size));
|
builder.add("size", Integer.toString(size));
|
||||||
builder.add("offset", Integer.toString(offset));
|
builder.add("offset", Integer.toString(offset));
|
||||||
|
|
||||||
String method;
|
String method;
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case MainFragment.SONGS_NEWEST:
|
case MainFragment.SONGS_NEWEST:
|
||||||
method = "getNewaddedSongs";
|
method = "getNewaddedSongs";
|
||||||
break;
|
break;
|
||||||
@ -505,66 +506,43 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
Builder builder= new FormBody.Builder();
|
|
||||||
builder.add("id", artistId);
|
|
||||||
builder.add("count", Integer.toString(size));
|
|
||||||
|
|
||||||
String url = getRestUrl(context, "getSimilarSongs2");
|
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(formBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getRandomSongs(int size, String musicFolderId, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getRandomSongs(int size, String musicFolderId, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("size", Integer.toString(size));
|
builder.add("size", Integer.toString(size));
|
||||||
|
|
||||||
if (musicFolderId != null && !"".equals(musicFolderId) && !Util.isTagBrowsing(context, getInstance(context))) {
|
if (genre != null && !"".equals(genre)) {
|
||||||
builder.add("musicFolderId", musicFolderId);
|
|
||||||
}
|
|
||||||
if(genre != null && !"".equals(genre)) {
|
|
||||||
builder.add("genre", genre);
|
builder.add("genre", genre);
|
||||||
}
|
}
|
||||||
if(startYear != null && !"".equals(startYear)) {
|
if (startYear != null && !"".equals(startYear)) {
|
||||||
// Check to make sure user isn't doing 2015 -> 2010 since Subsonic will return no results
|
// Check to make sure user isn't doing 2015 -> 2010 since Subsonic will return no results
|
||||||
if(endYear != null && !"".equals(endYear)) {
|
if (endYear != null && !"".equals(endYear)) {
|
||||||
try {
|
try {
|
||||||
int startYearInt = Integer.parseInt(startYear);
|
int startYearInt = Integer.parseInt(startYear);
|
||||||
int endYearInt = Integer.parseInt(endYear);
|
int endYearInt = Integer.parseInt(endYear);
|
||||||
|
|
||||||
if(startYearInt > endYearInt) {
|
if (startYearInt > endYearInt) {
|
||||||
String tmp = startYear;
|
String tmp = startYear;
|
||||||
startYear = endYear;
|
startYear = endYear;
|
||||||
endYear = tmp;
|
endYear = tmp;
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to convert start/end year into ints", e);
|
Log.w(TAG, "Failed to convert start/end year into ints", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add("fromYear", startYear);
|
builder.add("fromYear", startYear);
|
||||||
}
|
}
|
||||||
if(endYear != null && !"".equals(endYear)) {
|
if (endYear != null && !"".equals(endYear)) {
|
||||||
builder.add("toYear", endYear);
|
builder.add("toYear", endYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,12 +551,12 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,15 +574,15 @@ public class RESTMusicService implements MusicService {
|
|||||||
|
|
||||||
String url = getRestUrl(context, "getCoverArt");
|
String url = getRestUrl(context, "getCoverArt");
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("id", entry.getCoverArt());
|
builder.add("id", entry.getCoverArt());
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
InputStream in = response.body().byteStream();
|
InputStream in = response.body().byteStream();
|
||||||
@ -612,7 +590,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
byte[] bytes = Util.toByteArray(in);
|
byte[] bytes = Util.toByteArray(in);
|
||||||
|
|
||||||
// Handle case where partial was downloaded before being cancelled
|
// Handle case where partial was downloaded before being cancelled
|
||||||
if(task != null && task.isCancelled()) {
|
if (task != null && task.isCancelled()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +603,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size == 0 -> only want to download
|
// Size == 0 -> only want to download
|
||||||
if(size == 0) {
|
if (size == 0) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return FileUtil.getSampledBitmap(bytes, size);
|
return FileUtil.getSampledBitmap(bytes, size);
|
||||||
@ -638,8 +616,8 @@ public class RESTMusicService implements MusicService {
|
|||||||
public Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
public Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
||||||
|
|
||||||
OkHttpClient eagerClient = client.newBuilder()
|
OkHttpClient eagerClient = client.newBuilder()
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
String url = getRestUrl(context, "stream");
|
String url = getRestUrl(context, "stream");
|
||||||
|
|
||||||
@ -649,7 +627,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request.Builder requestBuilder= new Request.Builder();
|
Request.Builder requestBuilder = new Request.Builder();
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
requestBuilder.header("Range", "bytes=" + offset + "-");
|
requestBuilder.header("Range", "bytes=" + offset + "-");
|
||||||
}
|
}
|
||||||
@ -659,8 +637,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
|
|
||||||
Request request = requestBuilder.build();
|
Request request = requestBuilder.build();
|
||||||
|
|
||||||
Response response = eagerClient.newCall(request).execute();
|
return eagerClient.newCall(request).execute();
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -669,26 +646,26 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getGenres");
|
String url = getRestUrl(context, "getGenres");
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new GenreParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new GenreParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
Builder builder= new FormBody.Builder();
|
Builder builder = new FormBody.Builder();
|
||||||
builder.add("genre", genre);
|
builder.add("genre", genre);
|
||||||
builder.add("count", Integer.toString(count));
|
builder.add("count", Integer.toString(count));
|
||||||
builder.add("offset", Integer.toString(offset));
|
builder.add("offset", Integer.toString(offset));
|
||||||
|
|
||||||
// Add folder if it was set and is non null
|
// Add folder if it was set and is non null
|
||||||
int instance = getInstance(context);
|
int instance = getInstance(context);
|
||||||
if(Util.getAlbumListsPerFolder(context, instance)) {
|
if (Util.getAlbumListsPerFolder(context, instance)) {
|
||||||
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
String folderId = Util.getSelectedMusicFolderId(context, instance);
|
||||||
if(folderId != null) {
|
if (folderId != null) {
|
||||||
builder.add("musicFolderId", folderId);
|
builder.add("musicFolderId", folderId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -698,12 +675,12 @@ public class RESTMusicService implements MusicService {
|
|||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,17 +689,17 @@ public class RESTMusicService implements MusicService {
|
|||||||
String url = getRestUrl(context, "getUser");
|
String url = getRestUrl(context, "getUser");
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("username", username)
|
.add("username", username)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try (Response response = client.newCall(request).execute()) {
|
||||||
List<User> users = new UserParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
List<User> users = new UserParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||||
if(users.size() > 0) {
|
if (users.size() > 0) {
|
||||||
// Should only have returned one anyways
|
// Should only have returned one anyways
|
||||||
return users.get(0);
|
return users.get(0);
|
||||||
} else {
|
} else {
|
||||||
@ -731,91 +708,15 @@ public class RESTMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getBitmap(String method, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
|
||||||
// Synchronize on the url so that we don't download concurrently
|
|
||||||
synchronized (method) {
|
|
||||||
// Use cached file, if existing.
|
|
||||||
Bitmap bitmap = FileUtil.getMiscBitmap(context, method, size);
|
|
||||||
if(bitmap != null) {
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = getRestUrl(context, method);
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
InputStream in = response.body().byteStream();
|
|
||||||
|
|
||||||
byte[] bytes = Util.toByteArray(in);
|
|
||||||
if(task != null && task.isCancelled()) {
|
|
||||||
// Handle case where partial is downloaded and cancelled
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
|
||||||
out = new FileOutputStream(FileUtil.getMiscFile(context, url));
|
|
||||||
out.write(bytes);
|
|
||||||
} finally {
|
|
||||||
Util.close(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FileUtil.getSampledBitmap(bytes, size, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void savePlayQueue(List<MusicDirectory.Entry> songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
String url = getRestUrl(context, "savePlayQueue");
|
|
||||||
|
|
||||||
Builder builder= new FormBody.Builder();
|
|
||||||
|
|
||||||
builder.add("current", currentPlaying.getId());
|
|
||||||
builder.add("position", Integer.toString(position));
|
|
||||||
|
|
||||||
for(MusicDirectory.Entry song: songs) {
|
|
||||||
builder.add("id", song.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(formBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
new ErrorParser(context, getInstance(context)).parse(response.body().byteStream());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
String url = getRestUrl(context, "getPlayQueue");
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return new PlayQueueParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getOfflineSongId(String id, Context context, ProgressListener progressListener) throws Exception {
|
private String getOfflineSongId(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
if(cacheLocn != null && id.indexOf(cacheLocn) != -1) {
|
if (cacheLocn != null && id.contains(cacheLocn)) {
|
||||||
Pair<Integer, String> cachedSongId = SongDBHandler.getHandler(context).getIdFromPath(Util.getRestUrlHash(context, getInstance(context)), id);
|
Pair<Integer, String> cachedSongId = SongDBHandler.getHandler(context).getIdFromPath(Util.getRestUrlHash(context, getInstance(context)), id);
|
||||||
if(cachedSongId != null) {
|
if (cachedSongId != null) {
|
||||||
id = cachedSongId.getSecond();
|
id = cachedSongId.getSecond();
|
||||||
} else {
|
} else {
|
||||||
String searchCriteria = Util.parseOfflineIDSearch(context, id, cacheLocn);
|
String searchCriteria = Util.parseOfflineIDSearch(id, cacheLocn);
|
||||||
SearchCritera critera = new SearchCritera(searchCriteria, 0, 0, 1);
|
SearchCritera critera = new SearchCritera(searchCriteria, 0, 0, 1);
|
||||||
SearchResult result = search(critera, context, progressListener);
|
SearchResult result = search(critera, context, progressListener);
|
||||||
if (result.getSongs().size() == 1) {
|
if (result.getSongs().size() == 1) {
|
||||||
@ -828,12 +729,12 @@ public class RESTMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInstance(Integer instance) throws Exception {
|
public void setInstance(Integer instance) throws Exception {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInstance(Context context) {
|
public int getInstance(Context context) {
|
||||||
if(instance == null) {
|
if (instance == null) {
|
||||||
return Util.getActiveServer(context);
|
return Util.getActiveServer(context);
|
||||||
} else {
|
} else {
|
||||||
return instance;
|
return instance;
|
||||||
@ -846,7 +747,7 @@ public class RESTMusicService implements MusicService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRestUrl(Context context, String method, boolean allowAltAddress) {
|
public String getRestUrl(Context context, String method, boolean allowAltAddress) {
|
||||||
if(instance == null) {
|
if (instance == null) {
|
||||||
return Util.getRestUrl(context, method, allowAltAddress);
|
return Util.getRestUrl(context, method, allowAltAddress);
|
||||||
} else {
|
} else {
|
||||||
return Util.getRestUrl(context, method, instance, allowAltAddress);
|
return Util.getRestUrl(context, method, instance, allowAltAddress);
|
||||||
|
@ -18,41 +18,41 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractParser {
|
abstract class AbstractParser {
|
||||||
private static final String TAG = AbstractParser.class.getSimpleName();
|
private static final String TAG = AbstractParser.class.getSimpleName();
|
||||||
private static final String SUBSONIC_RESPONSE = "subsonic-response";
|
private static final String SUBSONIC_RESPONSE = "subsonic-response";
|
||||||
private static final String SUBSONIC = "subsonic";
|
|
||||||
|
|
||||||
protected final Context context;
|
final Context context;
|
||||||
protected final int instance;
|
private final int instance;
|
||||||
private XmlPullParser parser;
|
private XmlPullParser parser;
|
||||||
private boolean rootElementFound;
|
private boolean rootElementFound;
|
||||||
|
|
||||||
public AbstractParser(Context context, int instance) {
|
AbstractParser(Context context, int instance) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Context getContext() {
|
Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleError() throws Exception {
|
void handleError() throws Exception {
|
||||||
int code = getInteger("code");
|
int code = getInteger("code");
|
||||||
String message;
|
String message;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
@ -69,7 +69,7 @@ public abstract class AbstractParser {
|
|||||||
message = context.getResources().getString(R.string.parser_not_authenticated);
|
message = context.getResources().getString(R.string.parser_not_authenticated);
|
||||||
break;
|
break;
|
||||||
case 41:
|
case 41:
|
||||||
Util.setBlockTokenUse(context, instance, true);
|
Util.setBlockTokenUse(context, instance);
|
||||||
|
|
||||||
// Throw IOException so RESTMusicService knows to retry
|
// Throw IOException so RESTMusicService knows to retry
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
@ -80,77 +80,56 @@ public abstract class AbstractParser {
|
|||||||
message = get("message");
|
message = get("message");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw new SubsonicRESTException(code, message);
|
throw new SubsonicRESTException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateProgress(ProgressListener progressListener, int messageId) {
|
void updateProgress(ProgressListener progressListener, String message) {
|
||||||
if (progressListener != null) {
|
|
||||||
progressListener.updateProgress(messageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateProgress(ProgressListener progressListener, String message) {
|
|
||||||
if (progressListener != null) {
|
if (progressListener != null) {
|
||||||
progressListener.updateProgress(message);
|
progressListener.updateProgress(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getText() {
|
String getText() {
|
||||||
return parser.getText();
|
return parser.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String get(String name) {
|
String get(String name) {
|
||||||
return parser.getAttributeValue(null, name);
|
return parser.getAttributeValue(null, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean getBoolean(String name) {
|
boolean getBoolean() {
|
||||||
return "true".equals(get(name));
|
return "true".equals(get("isDir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Integer getInteger(String name) {
|
Integer getInteger(String name) {
|
||||||
String s = get(name);
|
String s = get(name);
|
||||||
try {
|
try {
|
||||||
return (s == null || "".equals(s)) ? null : Integer.valueOf(s);
|
return (s == null || "".equals(s)) ? null : Integer.valueOf(s);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to parse " + s + " into integer");
|
Log.w(TAG, "Failed to parse " + s + " into integer");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Long getLong(String name) {
|
void init(InputStream inputStream) throws Exception {
|
||||||
String s = get(name);
|
|
||||||
return s == null ? null : Long.valueOf(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Float getFloat(String name) {
|
|
||||||
String s = get(name);
|
|
||||||
return s == null ? null : Float.valueOf(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init(InputStream inputStream) throws Exception {
|
|
||||||
parser = Xml.newPullParser();
|
parser = Xml.newPullParser();
|
||||||
parser.setInput(inputStream, "UTF-8");
|
parser.setInput(inputStream, "UTF-8");
|
||||||
rootElementFound = false;
|
rootElementFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int nextParseEvent() throws Exception {
|
int nextParseEvent() throws Exception {
|
||||||
try {
|
return parser.next();
|
||||||
return parser.next();
|
|
||||||
} catch(Exception e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getElementName() {
|
String getElementName() {
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
if (SUBSONIC_RESPONSE.equals(name)) {
|
if (SUBSONIC_RESPONSE.equals(name)) {
|
||||||
rootElementFound = true;
|
rootElementFound = true;
|
||||||
String version = get("version");
|
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void validate() throws Exception {
|
void validate() throws Exception {
|
||||||
if (!rootElementFound) {
|
if (!rootElementFound) {
|
||||||
throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
|
throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -35,7 +35,7 @@ public class EntryListParser extends MusicDirectoryEntryParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
MusicDirectory dir = new MusicDirectory();
|
MusicDirectory dir = new MusicDirectory();
|
||||||
@ -46,7 +46,7 @@ public class EntryListParser extends MusicDirectoryEntryParser {
|
|||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if ("album".equals(name)) {
|
if ("album".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
if(get("isDir") == null) {
|
if (get("isDir") == null) {
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
}
|
}
|
||||||
dir.addChild(entry);
|
dir.addChild(entry);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -20,34 +20,29 @@ package net.nullsum.audinaut.service.parser;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.util.Log;
|
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Joshua Bahnsen
|
* @author Joshua Bahnsen
|
||||||
*/
|
*/
|
||||||
public class GenreParser extends AbstractParser {
|
public class GenreParser extends AbstractParser {
|
||||||
private static final String TAG = GenreParser.class.getSimpleName();
|
|
||||||
|
|
||||||
public GenreParser(Context context, int instance) {
|
public GenreParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Genre> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<Genre> parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
List<Genre> result = new ArrayList<Genre>();
|
List<Genre> result = new ArrayList<>();
|
||||||
|
|
||||||
Genre genre = null;
|
Genre genre = null;
|
||||||
|
|
||||||
@ -80,12 +75,7 @@ public class GenreParser extends AbstractParser {
|
|||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
Collections.sort(result, new Comparator<Genre>() {
|
Collections.sort(result, (genre1, genre2) -> genre1.getName().compareTo(genre2.getName()));
|
||||||
@Override
|
|
||||||
public int compare(Genre genre1, Genre genre2) {
|
|
||||||
return genre1.getName().compareTo(genre2.getName());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,25 +18,26 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
import net.nullsum.audinaut.domain.Indexes;
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import android.util.Log;
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
@ -51,15 +52,14 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
List<Artist> shortcuts = new ArrayList<Artist>();
|
List<Artist> shortcuts = new ArrayList<>();
|
||||||
List<MusicDirectory.Entry> entries = new ArrayList<MusicDirectory.Entry>();
|
List<MusicDirectory.Entry> entries = new ArrayList<>();
|
||||||
Long lastModified = null;
|
|
||||||
int eventType;
|
int eventType;
|
||||||
String index = "#";
|
String index = "#";
|
||||||
String ignoredArticles = null;
|
String ignoredArticles = null;
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
Map<String, Artist> artistList = new HashMap<String, Artist>();
|
Map<String, Artist> artistList = new HashMap<>();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
@ -67,7 +67,6 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if ("indexes".equals(name) || "artists".equals(name)) {
|
if ("indexes".equals(name) || "artists".equals(name)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
lastModified = getLong("lastModified");
|
|
||||||
ignoredArticles = get("ignoredArticles");
|
ignoredArticles = get("ignoredArticles");
|
||||||
} else if ("index".equals(name)) {
|
} else if ("index".equals(name)) {
|
||||||
index = get("name");
|
index = get("name");
|
||||||
@ -79,7 +78,7 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
artist.setIndex(index);
|
artist.setIndex(index);
|
||||||
|
|
||||||
// Combine the id's for the two artists
|
// Combine the id's for the two artists
|
||||||
if(artistList.containsKey(artist.getName())) {
|
if (artistList.containsKey(artist.getName())) {
|
||||||
Artist originalArtist = artistList.get(artist.getName());
|
Artist originalArtist = artistList.get(artist.getName());
|
||||||
originalArtist.setId(originalArtist.getId() + ";" + artist.getId());
|
originalArtist.setId(originalArtist.getId() + ";" + artist.getId());
|
||||||
} else {
|
} else {
|
||||||
@ -97,7 +96,7 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
shortcut.setName(get("name"));
|
shortcut.setName(get("name"));
|
||||||
shortcut.setIndex("*");
|
shortcut.setIndex("*");
|
||||||
shortcuts.add(shortcut);
|
shortcuts.add(shortcut);
|
||||||
} else if("child".equals(name)) {
|
} else if ("child".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
entries.add(entry);
|
entries.add(entry);
|
||||||
} else if ("error".equals(name)) {
|
} else if ("error".equals(name)) {
|
||||||
@ -108,7 +107,7 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
if(ignoredArticles != null) {
|
if (ignoredArticles != null) {
|
||||||
SharedPreferences.Editor prefs = Util.getPreferences(context).edit();
|
SharedPreferences.Editor prefs = Util.getPreferences(context).edit();
|
||||||
prefs.putString(Constants.CACHE_KEY_IGNORE, ignoredArticles);
|
prefs.putString(Constants.CACHE_KEY_IGNORE, ignoredArticles);
|
||||||
prefs.apply();
|
prefs.apply();
|
||||||
@ -124,6 +123,6 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||||
updateProgress(progressListener, msg);
|
updateProgress(progressListener, msg);
|
||||||
|
|
||||||
return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists, entries);
|
return new Indexes(shortcuts, artists, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,21 +25,21 @@ import net.nullsum.audinaut.domain.MusicDirectory;
|
|||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class MusicDirectoryEntryParser extends AbstractParser {
|
class MusicDirectoryEntryParser extends AbstractParser {
|
||||||
public MusicDirectoryEntryParser(Context context, int instance) {
|
MusicDirectoryEntryParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MusicDirectory.Entry parseEntry(String artist) {
|
MusicDirectory.Entry parseEntry(String artist) {
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||||
entry.setId(get("id"));
|
entry.setId(get("id"));
|
||||||
entry.setParent(get("parent"));
|
entry.setParent(get("parent"));
|
||||||
entry.setArtistId(get("artistId"));
|
entry.setArtistId(get("artistId"));
|
||||||
entry.setTitle(get("title"));
|
entry.setTitle(get("title"));
|
||||||
if(entry.getTitle() == null) {
|
if (entry.getTitle() == null) {
|
||||||
entry.setTitle(get("name"));
|
entry.setTitle(get("name"));
|
||||||
}
|
}
|
||||||
entry.setDirectory(getBoolean("isDir"));
|
entry.setDirectory(getBoolean());
|
||||||
entry.setCoverArt(get("coverArt"));
|
entry.setCoverArt(get("coverArt"));
|
||||||
entry.setArtist(get("artist"));
|
entry.setArtist(get("artist"));
|
||||||
entry.setYear(getInteger("year"));
|
entry.setYear(getInteger("year"));
|
||||||
@ -53,27 +53,14 @@ public class MusicDirectoryEntryParser extends AbstractParser {
|
|||||||
entry.setSuffix(get("suffix"));
|
entry.setSuffix(get("suffix"));
|
||||||
entry.setTranscodedContentType(get("transcodedContentType"));
|
entry.setTranscodedContentType(get("transcodedContentType"));
|
||||||
entry.setTranscodedSuffix(get("transcodedSuffix"));
|
entry.setTranscodedSuffix(get("transcodedSuffix"));
|
||||||
entry.setSize(getLong("size"));
|
|
||||||
entry.setDuration(getInteger("duration"));
|
entry.setDuration(getInteger("duration"));
|
||||||
entry.setBitRate(getInteger("bitRate"));
|
entry.setBitRate(getInteger("bitRate"));
|
||||||
entry.setPath(get("path"));
|
entry.setPath(get("path"));
|
||||||
entry.setDiscNumber(getInteger("discNumber"));
|
entry.setDiscNumber(getInteger("discNumber"));
|
||||||
|
} else if (!"".equals(artist)) {
|
||||||
String type = get("type");
|
|
||||||
} else if(!"".equals(artist)) {
|
|
||||||
entry.setPath(artist + "/" + entry.getTitle());
|
entry.setPath(artist + "/" + entry.getTitle());
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MusicDirectory.Entry parseArtist() {
|
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
|
||||||
|
|
||||||
entry.setId(get("id"));
|
|
||||||
entry.setTitle(get("name"));
|
|
||||||
entry.setPath(entry.getTitle());
|
|
||||||
entry.setDirectory(true);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,48 +19,42 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.Constants;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import net.nullsum.audinaut.util.Util;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static net.nullsum.audinaut.domain.MusicDirectory.*;
|
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class MusicDirectoryParser extends MusicDirectoryEntryParser {
|
public class MusicDirectoryParser extends MusicDirectoryEntryParser {
|
||||||
|
|
||||||
private static final String TAG = MusicDirectoryParser.class.getSimpleName();
|
|
||||||
|
|
||||||
public MusicDirectoryParser(Context context, int instance) {
|
public MusicDirectoryParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(String artist, InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(String artist, InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
MusicDirectory dir = new MusicDirectory();
|
MusicDirectory dir = new MusicDirectory();
|
||||||
int eventType;
|
int eventType;
|
||||||
boolean isArtist = false;
|
boolean isArtist = false;
|
||||||
Map<String, Entry> titleMap = new HashMap<String, Entry>();
|
Map<String, Entry> titleMap = new HashMap<>();
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if ("child".equals(name) || "song".equals(name)) {
|
if ("child".equals(name) || "song".equals(name)) {
|
||||||
Entry entry = parseEntry(artist);
|
Entry entry = parseEntry(artist);
|
||||||
entry.setGrandParent(dir.getParent());
|
|
||||||
|
|
||||||
// Only check for songs
|
// Only check for songs
|
||||||
if(!entry.isDirectory()) {
|
if (!entry.isDirectory()) {
|
||||||
// Check if duplicates
|
// Check if duplicates
|
||||||
String disc = (entry.getDiscNumber() != null) ? Integer.toString(entry.getDiscNumber()) : "";
|
String disc = (entry.getDiscNumber() != null) ? Integer.toString(entry.getDiscNumber()) : "";
|
||||||
String track = (entry.getTrack() != null) ? Integer.toString(entry.getTrack()) : "";
|
String track = (entry.getTrack() != null) ? Integer.toString(entry.getTrack()) : "";
|
||||||
@ -84,13 +78,9 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser {
|
|||||||
} else if ("directory".equals(name) || "artist".equals(name) || ("album".equals(name) && !isArtist)) {
|
} else if ("directory".equals(name) || "artist".equals(name) || ("album".equals(name) && !isArtist)) {
|
||||||
dir.setName(get("name"));
|
dir.setName(get("name"));
|
||||||
dir.setId(get("id"));
|
dir.setId(get("id"));
|
||||||
if(Util.isTagBrowsing(context, instance)) {
|
dir.setParent(get("artistId"));
|
||||||
dir.setParent(get("artistId"));
|
|
||||||
} else {
|
|
||||||
dir.setParent(get("parent"));
|
|
||||||
}
|
|
||||||
isArtist = true;
|
isArtist = true;
|
||||||
} else if("album".equals(name)) {
|
} else if ("album".equals(name)) {
|
||||||
Entry entry = parseEntry(artist);
|
Entry entry = parseEntry(artist);
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
dir.addChild(entry);
|
dir.addChild(entry);
|
||||||
|
@ -18,16 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import android.content.Context;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import android.content.Context;
|
import java.io.InputStream;
|
||||||
import net.nullsum.audinaut.R;
|
import java.util.ArrayList;
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
import java.util.List;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
@ -38,10 +37,10 @@ public class MusicFoldersParser extends AbstractParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MusicFolder> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<MusicFolder> parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
List<MusicFolder> result = new ArrayList<MusicFolder>();
|
List<MusicFolder> result = new ArrayList<>();
|
||||||
int eventType;
|
int eventType;
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Subsonic.
|
|
||||||
Subsonic 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.
|
|
||||||
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
Copyright 2015 (C) Scott Jackson
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.nullsum.audinaut.service.parser;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
||||||
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
|
|
||||||
public class PlayQueueParser extends MusicDirectoryEntryParser {
|
|
||||||
private static final String TAG = PlayQueueParser.class.getSimpleName();
|
|
||||||
|
|
||||||
public PlayQueueParser(Context context, int instance) {
|
|
||||||
super(context, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerQueue parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
|
||||||
init(inputStream);
|
|
||||||
|
|
||||||
PlayerQueue state = new PlayerQueue();
|
|
||||||
String currentId = null;
|
|
||||||
int eventType;
|
|
||||||
do {
|
|
||||||
eventType = nextParseEvent();
|
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
|
||||||
String name = getElementName();
|
|
||||||
if("playQueue".equals(name)) {
|
|
||||||
currentId = get("current");
|
|
||||||
state.currentPlayingPosition = getInteger("position");
|
|
||||||
try {
|
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
|
|
||||||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
state.changed = dateFormat.parse(get("changed"));
|
|
||||||
} catch (ParseException e) {
|
|
||||||
state.changed = null;
|
|
||||||
}
|
|
||||||
} else if ("entry".equals(name)) {
|
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
|
||||||
// Only add songs
|
|
||||||
state.songs.add(entry);
|
|
||||||
} else if ("error".equals(name)) {
|
|
||||||
handleError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
|
||||||
|
|
||||||
if(currentId != null) {
|
|
||||||
for (MusicDirectory.Entry entry : state.songs) {
|
|
||||||
if (entry.getId().equals(currentId)) {
|
|
||||||
state.currentPlayingIndex = state.songs.indexOf(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.currentPlayingIndex = 0;
|
|
||||||
state.currentPlayingPosition = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate();
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,9 +19,9 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -35,7 +35,7 @@ public class PlaylistParser extends MusicDirectoryEntryParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
MusicDirectory dir = new MusicDirectory();
|
MusicDirectory dir = new MusicDirectory();
|
||||||
|
@ -21,7 +21,7 @@ package net.nullsum.audinaut.service.parser;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -37,10 +37,10 @@ public class PlaylistsParser extends AbstractParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Playlist> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<Playlist> parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
List<Playlist> result = new ArrayList<Playlist>();
|
List<Playlist> result = new ArrayList<>();
|
||||||
int eventType;
|
int eventType;
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -35,7 +35,7 @@ public class RandomSongsParser extends MusicDirectoryEntryParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
MusicDirectory dir = new MusicDirectory();
|
MusicDirectory dir = new MusicDirectory();
|
||||||
|
@ -19,16 +19,16 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.SearchResult;
|
import net.nullsum.audinaut.domain.SearchResult;
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
@ -39,12 +39,12 @@ public class SearchResult2Parser extends MusicDirectoryEntryParser {
|
|||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResult parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public SearchResult parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
|
List<MusicDirectory.Entry> albums = new ArrayList<>();
|
||||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
List<MusicDirectory.Entry> songs = new ArrayList<>();
|
||||||
int eventType;
|
int eventType;
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
|
@ -4,16 +4,10 @@ package net.nullsum.audinaut.service.parser;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class SubsonicRESTException extends Exception {
|
class SubsonicRESTException extends Exception {
|
||||||
|
|
||||||
private final int code;
|
public SubsonicRESTException(String message) {
|
||||||
|
|
||||||
public SubsonicRESTException(int code, String message) {
|
|
||||||
super(message);
|
super(message);
|
||||||
this.code = code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,12 @@
|
|||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
|
import net.nullsum.audinaut.domain.User;
|
||||||
|
import net.nullsum.audinaut.domain.User.Setting;
|
||||||
|
import net.nullsum.audinaut.service.MusicService;
|
||||||
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
@ -24,24 +29,15 @@ import java.io.InputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
|
||||||
import net.nullsum.audinaut.domain.User;
|
|
||||||
import net.nullsum.audinaut.domain.User.MusicFolderSetting;
|
|
||||||
import net.nullsum.audinaut.domain.User.Setting;
|
|
||||||
import net.nullsum.audinaut.service.MusicService;
|
|
||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
||||||
import net.nullsum.audinaut.util.ProgressListener;
|
|
||||||
|
|
||||||
public class UserParser extends AbstractParser {
|
public class UserParser extends AbstractParser {
|
||||||
private static final String TAG = UserParser.class.getSimpleName();
|
|
||||||
|
|
||||||
public UserParser(Context context, int instance) {
|
public UserParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<User> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<User> parse(InputStream inputStream) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
List<User> result = new ArrayList<User>();
|
List<User> result = new ArrayList<>();
|
||||||
List<MusicFolder> musicFolders = null;
|
List<MusicFolder> musicFolders = null;
|
||||||
User user = null;
|
User user = null;
|
||||||
int eventType;
|
int eventType;
|
||||||
@ -54,9 +50,7 @@ public class UserParser extends AbstractParser {
|
|||||||
if ("user".equals(tagName)) {
|
if ("user".equals(tagName)) {
|
||||||
user = new User();
|
user = new User();
|
||||||
|
|
||||||
user.setUsername(get("username"));
|
for (String role : User.ROLES) {
|
||||||
user.setEmail(get("email"));
|
|
||||||
for(String role: User.ROLES) {
|
|
||||||
parseSetting(user, role);
|
parseSetting(user, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,22 +58,22 @@ public class UserParser extends AbstractParser {
|
|||||||
} else if ("error".equals(tagName)) {
|
} else if ("error".equals(tagName)) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
} else if(eventType == XmlPullParser.TEXT) {
|
} else if (eventType == XmlPullParser.TEXT) {
|
||||||
if("folder".equals(tagName)) {
|
if ("folder".equals(tagName)) {
|
||||||
String id = getText();
|
String id = getText();
|
||||||
if(musicFolders == null) {
|
if (musicFolders == null) {
|
||||||
musicFolders = getMusicFolders();
|
musicFolders = getMusicFolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user != null) {
|
if (user != null) {
|
||||||
if(user.getMusicFolderSettings() == null) {
|
if (user.getMusicFolderSettings() == null) {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
user.addMusicFolder(musicFolder);
|
user.addMusicFolder(musicFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Setting musicFolder: user.getMusicFolderSettings()) {
|
for (Setting musicFolder : user.getMusicFolderSettings()) {
|
||||||
if(musicFolder.getName().equals(id)) {
|
if (musicFolder.getName().equals(id)) {
|
||||||
musicFolder.setValue(true);
|
musicFolder.setValue(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -94,14 +88,14 @@ public class UserParser extends AbstractParser {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MusicFolder> getMusicFolders() throws Exception{
|
private List<MusicFolder> getMusicFolders() throws Exception {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
return musicService.getMusicFolders(false, context, null);
|
return musicService.getMusicFolders(false, context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseSetting(User user, String name) {
|
private void parseSetting(User user, String name) {
|
||||||
String value = get(name);
|
String value = get(name);
|
||||||
if(value != null) {
|
if (value != null) {
|
||||||
user.addSetting(name, "true".equals(value));
|
user.addSetting(name, "true".equals(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,24 +21,25 @@ package net.nullsum.audinaut.updates;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Scott
|
* @author Scott
|
||||||
*/
|
*/
|
||||||
public class Updater {
|
public class Updater {
|
||||||
protected String TAG = Updater.class.getSimpleName();
|
private final int version;
|
||||||
protected int version;
|
String TAG = Updater.class.getSimpleName();
|
||||||
protected Context context;
|
private Context context;
|
||||||
|
|
||||||
public Updater(int version) {
|
public Updater(int version) {
|
||||||
// 5.2 should show as 520 instead of 52
|
// 5.2 should show as 520 instead of 52
|
||||||
if(version < 100) {
|
if (version < 100) {
|
||||||
version *= 10;
|
version *= 10;
|
||||||
}
|
}
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@ -46,34 +47,41 @@ public class Updater {
|
|||||||
|
|
||||||
public void checkUpdates(Context context) {
|
public void checkUpdates(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
List<Updater> updaters = new ArrayList<Updater>();
|
List<Updater> updaters = new ArrayList<>();
|
||||||
updaters.add(new UpdaterSongPress());
|
updaters.add(new UpdaterSongPress());
|
||||||
|
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
int lastVersion = prefs.getInt(Constants.LAST_VERSION, 0);
|
int lastVersion = prefs.getInt(Constants.LAST_VERSION, 0);
|
||||||
if(lastVersion == 0) {
|
if (lastVersion == 0) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.LAST_VERSION, version);
|
editor.putInt(Constants.LAST_VERSION, version);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
} else if (version > lastVersion) {
|
||||||
else if(version > lastVersion) {
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.LAST_VERSION, version);
|
editor.putInt(Constants.LAST_VERSION, version);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
Log.i(TAG, "Updating from version " + lastVersion + " to " + version);
|
Log.i(TAG, "Updating from version " + lastVersion + " to " + version);
|
||||||
for(Updater updater: updaters) {
|
for (Updater updater : updaters) {
|
||||||
if(updater.shouldUpdate(lastVersion)) {
|
if (updater.shouldUpdate(lastVersion)) {
|
||||||
new BackgroundUpdate(context, updater).execute();
|
new BackgroundUpdate(context, updater).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
private String getName() {
|
||||||
return this.TAG;
|
return this.TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldUpdate(int version) {
|
||||||
|
return this.version > version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(Context context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private class BackgroundUpdate extends SilentBackgroundTask<Void> {
|
private class BackgroundUpdate extends SilentBackgroundTask<Void> {
|
||||||
private final Updater updater;
|
private final Updater updater;
|
||||||
|
|
||||||
@ -86,17 +94,10 @@ public class Updater {
|
|||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
try {
|
try {
|
||||||
updater.update(context);
|
updater.update(context);
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to run update for " + updater.getName());
|
Log.w(TAG, "Failed to run update for " + updater.getName());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldUpdate(int version) {
|
|
||||||
return this.version > version;
|
|
||||||
}
|
|
||||||
public void update(Context context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import android.content.SharedPreferences;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class UpdaterSongPress extends Updater {
|
class UpdaterSongPress extends Updater {
|
||||||
public UpdaterSongPress() {
|
public UpdaterSongPress() {
|
||||||
super(521);
|
super(521);
|
||||||
TAG = this.getClass().getSimpleName();
|
TAG = this.getClass().getSimpleName();
|
||||||
@ -33,7 +33,7 @@ public class UpdaterSongPress extends Updater {
|
|||||||
boolean playNowAfter = prefs.getBoolean("playNowAfter", true);
|
boolean playNowAfter = prefs.getBoolean("playNowAfter", true);
|
||||||
|
|
||||||
// Migrate the old preference so behavior stays the same
|
// Migrate the old preference so behavior stays the same
|
||||||
if(playNowAfter == false) {
|
if (!playNowAfter) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION, "single");
|
editor.putString(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION, "single");
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
@ -18,85 +18,73 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.view.ErrorDialog;
|
import net.nullsum.audinaut.view.ErrorDialog;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public abstract class BackgroundTask<T> implements ProgressListener {
|
public abstract class BackgroundTask<T> implements ProgressListener {
|
||||||
|
static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<>(10);
|
||||||
private static final String TAG = BackgroundTask.class.getSimpleName();
|
private static final String TAG = BackgroundTask.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
protected AtomicBoolean cancelled = new AtomicBoolean(false);
|
|
||||||
protected OnCancelListener cancelListener;
|
|
||||||
protected Runnable onCompletionListener = null;
|
|
||||||
protected Task task;
|
|
||||||
|
|
||||||
private static final int DEFAULT_CONCURRENCY = 8;
|
private static final int DEFAULT_CONCURRENCY = 8;
|
||||||
private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>());
|
private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>());
|
||||||
protected static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<BackgroundTask.Task>(10);
|
|
||||||
private static Handler handler = null;
|
private static Handler handler = null;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Not called from main thread
|
// Not called from main thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackgroundTask(Context context) {
|
final AtomicBoolean cancelled = new AtomicBoolean(false);
|
||||||
|
private final Context context;
|
||||||
|
private final Runnable onCompletionListener = null;
|
||||||
|
Task task;
|
||||||
|
|
||||||
|
BackgroundTask(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
if(threads.size() < DEFAULT_CONCURRENCY) {
|
if (threads.size() < DEFAULT_CONCURRENCY) {
|
||||||
for(int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) {
|
for (int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) {
|
||||||
Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i));
|
Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i));
|
||||||
threads.add(thread);
|
threads.add(thread);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(handler == null) {
|
if (handler == null) {
|
||||||
try {
|
try {
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// Not called from main thread
|
// Not called from main thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopThreads() {
|
private Activity getActivity() {
|
||||||
for(Thread thread: threads) {
|
|
||||||
thread.interrupt();
|
|
||||||
}
|
|
||||||
threads.clear();
|
|
||||||
queue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Activity getActivity() {
|
|
||||||
return (context instanceof Activity) ? ((Activity) context) : null;
|
return (context instanceof Activity) ? ((Activity) context) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Context getContext() {
|
Handler getHandler() {
|
||||||
return context;
|
|
||||||
}
|
|
||||||
protected Handler getHandler() {
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +97,7 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
Log.w(TAG, "Got exception: " + error, error);
|
Log.w(TAG, "Got exception: " + error, error);
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if(activity != null) {
|
if (activity != null) {
|
||||||
new ErrorDialog(activity, getErrorMessage(error), true);
|
new ErrorDialog(activity, getErrorMessage(error), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,39 +128,27 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
if(cancelled.compareAndSet(false, true)) {
|
if (cancelled.compareAndSet(false, true)) {
|
||||||
if(isRunning()) {
|
if (isRunning()) {
|
||||||
if(cancelListener != null) {
|
task.cancel();
|
||||||
cancelListener.onCancel();
|
|
||||||
} else {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task = null;
|
task = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return cancelled.get();
|
return cancelled.get();
|
||||||
}
|
}
|
||||||
public void setOnCancelListener(OnCancelListener listener) {
|
|
||||||
cancelListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
if(task == null) {
|
return task != null && task.isRunning();
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return task.isRunning();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract void updateProgress(final String message);
|
public abstract void updateProgress(final String message);
|
||||||
|
|
||||||
@Override
|
public void updateProgress() {
|
||||||
public void updateProgress(int messageId) {
|
updateProgress(context.getResources().getString(R.string.settings_testing_connection));
|
||||||
updateProgress(context.getResources().getString(messageId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -180,17 +156,13 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnCompletionListener(Runnable onCompletionListener) {
|
class Task {
|
||||||
this.onCompletionListener = onCompletionListener;
|
private final AtomicBoolean taskStart = new AtomicBoolean(false);
|
||||||
}
|
|
||||||
|
|
||||||
protected class Task {
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private AtomicBoolean taskStart = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
private void execute() throws Exception {
|
private void execute() throws Exception {
|
||||||
// Don't run if cancelled already
|
// Don't run if cancelled already
|
||||||
if(isCancelled()) {
|
if (isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,60 +171,54 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
taskStart.set(true);
|
taskStart.set(true);
|
||||||
|
|
||||||
final T result = doInBackground();
|
final T result = doInBackground();
|
||||||
if(isCancelled()) {
|
if (isCancelled()) {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handler != null) {
|
if (handler != null) {
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> {
|
||||||
@Override
|
if (!isCancelled()) {
|
||||||
public void run() {
|
try {
|
||||||
if (!isCancelled()) {
|
onDone(result);
|
||||||
try {
|
} catch (Throwable t) {
|
||||||
onDone(result);
|
if (!isCancelled()) {
|
||||||
} catch (Throwable t) {
|
try {
|
||||||
if(!isCancelled()) {
|
onError(t);
|
||||||
try {
|
} catch (Exception e) {
|
||||||
onError(t);
|
// Don't care
|
||||||
} catch(Exception e) {
|
|
||||||
// Don't care
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskStart.set(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
taskStart.set(false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
}
|
}
|
||||||
} catch(InterruptedException interrupt) {
|
} catch (InterruptedException interrupt) {
|
||||||
if(taskStart.get()) {
|
if (taskStart.get()) {
|
||||||
// Don't exit root thread if task cancelled
|
// Don't exit root thread if task cancelled
|
||||||
throw interrupt;
|
throw interrupt;
|
||||||
}
|
}
|
||||||
} catch(final Throwable t) {
|
} catch (final Throwable t) {
|
||||||
if(isCancelled()) {
|
if (isCancelled()) {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handler != null) {
|
if (handler != null) {
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> {
|
||||||
@Override
|
if (!isCancelled()) {
|
||||||
public void run() {
|
try {
|
||||||
if(!isCancelled()) {
|
onError(t);
|
||||||
try {
|
} catch (Exception e) {
|
||||||
onError(t);
|
// Don't care
|
||||||
} catch(Exception e) {
|
|
||||||
// Don't care
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
taskStart.set(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
taskStart.set(false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
@ -263,28 +229,25 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
if(taskStart.compareAndSet(true, false)) {
|
if (taskStart.compareAndSet(true, false)) {
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
if(Thread.interrupted()) {
|
return Thread.interrupted() || BackgroundTask.this.isCancelled();
|
||||||
return true;
|
|
||||||
} else if(BackgroundTask.this.isCancelled()) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDone(T result) {
|
public void onDone(T result) {
|
||||||
done(result);
|
done(result);
|
||||||
|
|
||||||
if(onCompletionListener != null) {
|
if (onCompletionListener != null) {
|
||||||
onCompletionListener.run();
|
onCompletionListener.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
error(t);
|
error(t);
|
||||||
}
|
}
|
||||||
@ -304,22 +267,18 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
while(running) {
|
while (running) {
|
||||||
try {
|
try {
|
||||||
Task task = queue.take();
|
Task task = queue.take();
|
||||||
task.execute();
|
task.execute();
|
||||||
} catch(InterruptedException stop) {
|
} catch (InterruptedException stop) {
|
||||||
Log.e(TAG, "Thread died");
|
Log.e(TAG, "Thread died");
|
||||||
running = false;
|
running = false;
|
||||||
threads.remove(Thread.currentThread());
|
threads.remove(Thread.currentThread());
|
||||||
} catch(Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unexpected crash in BackgroundTask thread", t);
|
Log.e(TAG, "Unexpected crash in BackgroundTask thread", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface OnCancelListener {
|
|
||||||
void onCancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,16 @@ import java.io.File;
|
|||||||
|
|
||||||
public interface BufferFile {
|
public interface BufferFile {
|
||||||
File getFile();
|
File getFile();
|
||||||
|
|
||||||
Long getContentLength();
|
Long getContentLength();
|
||||||
|
|
||||||
long getEstimatedSize();
|
long getEstimatedSize();
|
||||||
|
|
||||||
boolean isWorkDone();
|
boolean isWorkDone();
|
||||||
|
|
||||||
void onStart();
|
void onStart();
|
||||||
|
|
||||||
void onStop();
|
void onStop();
|
||||||
|
|
||||||
void onResume();
|
void onResume();
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,8 @@ package net.nullsum.audinaut.util;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.util.FileProxy;
|
|
||||||
|
|
||||||
public class BufferProxy extends FileProxy {
|
public class BufferProxy extends FileProxy {
|
||||||
private static final String TAG = BufferProxy.class.getSimpleName();
|
private BufferFile progress;
|
||||||
protected BufferFile progress;
|
|
||||||
|
|
||||||
public BufferProxy(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ProxyTask getTask(Socket client) {
|
protected ProxyTask getTask(Socket client) {
|
||||||
return new BufferFileTask(client);
|
return new BufferFileTask(client);
|
||||||
@ -51,11 +42,12 @@ public class BufferProxy extends FileProxy {
|
|||||||
@Override
|
@Override
|
||||||
Long getContentLength() {
|
Long getContentLength() {
|
||||||
Long contentLength = progress.getContentLength();
|
Long contentLength = progress.getContentLength();
|
||||||
if(contentLength == null && progress.isWorkDone()) {
|
if (contentLength == null && progress.isWorkDone()) {
|
||||||
contentLength = file.length();
|
contentLength = file.length();
|
||||||
}
|
}
|
||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
long getFileSize() {
|
long getFileSize() {
|
||||||
return progress.getEstimatedSize();
|
return progress.getEstimatedSize();
|
||||||
@ -65,10 +57,12 @@ public class BufferProxy extends FileProxy {
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
progress.onStart();
|
progress.onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
progress.onStop();
|
progress.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
progress.onResume();
|
progress.onResume();
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import android.os.StatFs;
|
import android.os.StatFs;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
import net.nullsum.audinaut.service.MediaStoreService;
|
import net.nullsum.audinaut.service.MediaStoreService;
|
||||||
|
|
||||||
import java.util.*;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
@ -41,9 +40,11 @@ public class CacheCleaner {
|
|||||||
public void clean() {
|
public void clean() {
|
||||||
new BackgroundCleanup(context).execute();
|
new BackgroundCleanup(context).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanSpace() {
|
public void cleanSpace() {
|
||||||
new BackgroundSpaceCleanup(context).execute();
|
new BackgroundSpaceCleanup(context).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanPlaylists(List<Playlist> playlists) {
|
public void cleanPlaylists(List<Playlist> playlists) {
|
||||||
new BackgroundPlaylistsCleanup(context, playlists).execute();
|
new BackgroundPlaylistsCleanup(context, playlists).execute();
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ public class CacheCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long getMinimumDelete(List<File> files, List<File> pinned) {
|
private long getMinimumDelete(List<File> files, List<File> pinned) {
|
||||||
if(files.size() == 0) {
|
if (files.size() == 0) {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,8 +76,8 @@ public class CacheCleaner {
|
|||||||
|
|
||||||
// Ensure that file system is not more than 95% full.
|
// Ensure that file system is not more than 95% full.
|
||||||
StatFs stat = new StatFs(files.get(0).getPath());
|
StatFs stat = new StatFs(files.get(0).getPath());
|
||||||
long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
long bytesTotalFs = stat.getBlockCountLong() * stat.getBlockSizeLong();
|
||||||
long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
long bytesAvailableFs = stat.getAvailableBlocksLong() * stat.getBlockSizeLong();
|
||||||
long bytesUsedFs = bytesTotalFs - bytesAvailableFs;
|
long bytesUsedFs = bytesTotalFs - bytesAvailableFs;
|
||||||
long minFsAvailability = bytesTotalFs - MIN_FREE_SPACE;
|
long minFsAvailability = bytesTotalFs - MIN_FREE_SPACE;
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ public class CacheCleaner {
|
|||||||
|
|
||||||
long bytesDeleted = 0L;
|
long bytesDeleted = 0L;
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if(!deletePartials && bytesDeleted > bytesToDelete) break;
|
if (!deletePartials && bytesDeleted > bytesToDelete) break;
|
||||||
|
|
||||||
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) {
|
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) {
|
||||||
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) {
|
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) {
|
||||||
@ -134,22 +135,19 @@ public class CacheCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sortByAscendingModificationTime(List<File> files) {
|
private void sortByAscendingModificationTime(List<File> files) {
|
||||||
Collections.sort(files, new Comparator<File>() {
|
Collections.sort(files, (a, b) -> {
|
||||||
@Override
|
if (a.lastModified() < b.lastModified()) {
|
||||||
public int compare(File a, File b) {
|
return -1;
|
||||||
if (a.lastModified() < b.lastModified()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.lastModified() > b.lastModified()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
if (a.lastModified() > b.lastModified()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<File> findUndeletableFiles() {
|
private Set<File> findUndeletableFiles() {
|
||||||
Set<File> undeletable = new HashSet<File>(5);
|
Set<File> undeletable = new HashSet<>(5);
|
||||||
|
|
||||||
for (DownloadFile downloadFile : downloadService.getDownloads()) {
|
for (DownloadFile downloadFile : downloadService.getDownloads()) {
|
||||||
undeletable.add(downloadFile.getPartialFile());
|
undeletable.add(downloadFile.getPartialFile());
|
||||||
@ -163,30 +161,30 @@ public class CacheCleaner {
|
|||||||
private void cleanupCoverArt(Context context) {
|
private void cleanupCoverArt(Context context) {
|
||||||
File dir = FileUtil.getAlbumArtDirectory(context);
|
File dir = FileUtil.getAlbumArtDirectory(context);
|
||||||
|
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<>();
|
||||||
long bytesUsed = 0L;
|
long bytesUsed = 0L;
|
||||||
for(File file: dir.listFiles()) {
|
for (File file : dir.listFiles()) {
|
||||||
if(file.isFile()) {
|
if (file.isFile()) {
|
||||||
files.add(file);
|
files.add(file);
|
||||||
bytesUsed += file.length();
|
bytesUsed += file.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't waste time sorting if under limit already
|
// Don't waste time sorting if under limit already
|
||||||
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
if (bytesUsed < MAX_COVER_ART_SPACE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
long bytesDeleted = 0L;
|
long bytesDeleted = 0L;
|
||||||
for(File file: files) {
|
for (File file : files) {
|
||||||
// End as soon as the space used is below the threshold
|
// End as soon as the space used is below the threshold
|
||||||
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
if (bytesUsed < MAX_COVER_ART_SPACE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
long bytes = file.length();
|
long bytes = file.length();
|
||||||
if(file.delete()) {
|
if (file.delete()) {
|
||||||
bytesUsed -= bytes;
|
bytesUsed -= bytes;
|
||||||
bytesDeleted += bytes;
|
bytesDeleted += bytes;
|
||||||
}
|
}
|
||||||
@ -208,9 +206,9 @@ public class CacheCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<>();
|
||||||
List<File> pinned = new ArrayList<File>();
|
List<File> pinned = new ArrayList<>();
|
||||||
List<File> dirs = new ArrayList<File>();
|
List<File> dirs = new ArrayList<>();
|
||||||
|
|
||||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
@ -243,13 +241,13 @@ public class CacheCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<>();
|
||||||
List<File> pinned = new ArrayList<File>();
|
List<File> pinned = new ArrayList<>();
|
||||||
List<File> dirs = new ArrayList<File>();
|
List<File> dirs = new ArrayList<>();
|
||||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
||||||
|
|
||||||
long bytesToDelete = getMinimumDelete(files, pinned);
|
long bytesToDelete = getMinimumDelete(files, pinned);
|
||||||
if(bytesToDelete > 0L) {
|
if (bytesToDelete > 0L) {
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
Set<File> undeletable = findUndeletableFiles();
|
Set<File> undeletable = findUndeletableFiles();
|
||||||
deleteFiles(files, undeletable, bytesToDelete, false);
|
deleteFiles(files, undeletable, bytesToDelete, false);
|
||||||
@ -279,7 +277,7 @@ public class CacheCleaner {
|
|||||||
playlistFiles.remove(FileUtil.getPlaylistFile(context, server, playlist.getName()));
|
playlistFiles.remove(FileUtil.getPlaylistFile(context, server, playlist.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(File playlist : playlistFiles) {
|
for (File playlist : playlistFiles) {
|
||||||
playlist.delete();
|
playlist.delete();
|
||||||
}
|
}
|
||||||
} catch (RuntimeException x) {
|
} catch (RuntimeException x) {
|
||||||
|
@ -37,7 +37,6 @@ public final class Constants {
|
|||||||
public static final String INTENT_EXTRA_NAME_DIRECTORY = "subsonic.directory";
|
public static final String INTENT_EXTRA_NAME_DIRECTORY = "subsonic.directory";
|
||||||
public static final String INTENT_EXTRA_NAME_CHILD_ID = "subsonic.child.id";
|
public static final String INTENT_EXTRA_NAME_CHILD_ID = "subsonic.child.id";
|
||||||
public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist";
|
public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist";
|
||||||
public static final String INTENT_EXTRA_NAME_TITLE = "subsonic.title";
|
|
||||||
public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall";
|
public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall";
|
||||||
public static final String INTENT_EXTRA_NAME_QUERY = "subsonic.query";
|
public static final String INTENT_EXTRA_NAME_QUERY = "subsonic.query";
|
||||||
public static final String INTENT_EXTRA_NAME_PLAYLIST_ID = "subsonic.playlist.id";
|
public static final String INTENT_EXTRA_NAME_PLAYLIST_ID = "subsonic.playlist.id";
|
||||||
@ -48,18 +47,14 @@ public final class Constants {
|
|||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_SIZE = "subsonic.albumlistsize";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_SIZE = "subsonic.albumlistsize";
|
||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET = "subsonic.albumlistoffset";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET = "subsonic.albumlistoffset";
|
||||||
public static final String INTENT_EXTRA_NAME_SHUFFLE = "subsonic.shuffle";
|
public static final String INTENT_EXTRA_NAME_SHUFFLE = "subsonic.shuffle";
|
||||||
public static final String INTENT_EXTRA_REQUEST_SEARCH = "subsonic.requestsearch";
|
public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit";
|
||||||
public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit" ;
|
|
||||||
public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download";
|
public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download";
|
||||||
public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view";
|
public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view";
|
||||||
public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album";
|
public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album";
|
||||||
public static final String INTENT_EXTRA_NAME_SHARE = "subsonic.share";
|
|
||||||
public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType";
|
public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType";
|
||||||
public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings";
|
public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings";
|
||||||
public static final String INTENT_EXTRA_SEARCH_SONG = "searchSong";
|
public static final String INTENT_EXTRA_SEARCH_SONG = "searchSong";
|
||||||
public static final String INTENT_EXTRA_TOP_TRACKS = "topTracks";
|
public static final String INTENT_EXTRA_TOP_TRACKS = "topTracks";
|
||||||
public static final String INTENT_EXTRA_PLAY_LAST = "playLast";
|
|
||||||
public static final String INTENT_EXTRA_ENTRY = "passedEntry";
|
|
||||||
|
|
||||||
// Preferences keys.
|
// Preferences keys.
|
||||||
public static final String PREFERENCES_KEY_SERVER_KEY = "server";
|
public static final String PREFERENCES_KEY_SERVER_KEY = "server";
|
||||||
@ -76,7 +71,6 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
|
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
|
||||||
public static final String PREFERENCES_KEY_USERNAME = "username";
|
public static final String PREFERENCES_KEY_USERNAME = "username";
|
||||||
public static final String PREFERENCES_KEY_PASSWORD = "password";
|
public static final String PREFERENCES_KEY_PASSWORD = "password";
|
||||||
public static final String PREFERENCES_KEY_INSTALL_TIME = "installTime";
|
|
||||||
public static final String PREFERENCES_KEY_THEME = "theme";
|
public static final String PREFERENCES_KEY_THEME = "theme";
|
||||||
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
|
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
|
||||||
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";
|
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";
|
||||||
@ -98,7 +92,6 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear";
|
public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear";
|
public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre";
|
public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre";
|
||||||
public static final String PREFERENCES_KEY_KEEP_SCREEN_ON = "keepScreenOn";
|
|
||||||
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
|
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
|
||||||
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
|
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
|
||||||
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
|
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
|
||||||
@ -106,7 +99,6 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
|
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
|
||||||
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
|
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_MODE = "shuffleMode2";
|
public static final String PREFERENCES_KEY_SHUFFLE_MODE = "shuffleMode2";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_MODE_EXTRA = "shuffleModeExtra";
|
|
||||||
public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled";
|
public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled";
|
||||||
public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval";
|
public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval";
|
||||||
public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi";
|
public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi";
|
||||||
@ -115,8 +107,6 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect";
|
public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect";
|
||||||
public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget";
|
public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget";
|
||||||
public static final String PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled";
|
public static final String PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled";
|
||||||
public static final String PREFERENCES_KEY_SHARED_ENABLED = "sharedEnabled";
|
|
||||||
public static final String PREFERENCES_KEY_OPEN_TO_TAB = "openToTab";
|
|
||||||
// public static final String PREFERENCES_KEY_PLAY_NOW_AFTER = "playNowAfter";
|
// public static final String PREFERENCES_KEY_PLAY_NOW_AFTER = "playNowAfter";
|
||||||
public static final String PREFERENCES_KEY_SONG_PRESS_ACTION = "songPressAction";
|
public static final String PREFERENCES_KEY_SONG_PRESS_ACTION = "songPressAction";
|
||||||
public static final String PREFERENCES_KEY_LARGE_ALBUM_ART = "largeAlbumArt";
|
public static final String PREFERENCES_KEY_LARGE_ALBUM_ART = "largeAlbumArt";
|
||||||
@ -126,7 +116,7 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE= "replayGainType";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE = "replayGainType";
|
||||||
public static final String PREFERENCES_KEY_ALBUMS_PER_FOLDER = "albumsPerFolder";
|
public static final String PREFERENCES_KEY_ALBUMS_PER_FOLDER = "albumsPerFolder";
|
||||||
public static final String PREFERENCES_KEY_FIRST_LEVEL_ARTIST = "firstLevelArtist";
|
public static final String PREFERENCES_KEY_FIRST_LEVEL_ARTIST = "firstLevelArtist";
|
||||||
public static final String PREFERENCES_KEY_START_ON_HEADPHONES = "startOnHeadphones";
|
public static final String PREFERENCES_KEY_START_ON_HEADPHONES = "startOnHeadphones";
|
||||||
@ -134,12 +124,6 @@ public final class Constants {
|
|||||||
public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum";
|
public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum";
|
||||||
public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue";
|
public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue";
|
||||||
public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode";
|
public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode";
|
||||||
public static final String PREFERENCES_KEY_HEADS_UP_NOTIFICATION = "headsUpNotification";
|
|
||||||
|
|
||||||
public static final String OFFLINE_STAR_COUNT = "starCount";
|
|
||||||
public static final String OFFLINE_STAR_ID = "starID";
|
|
||||||
public static final String OFFLINE_STAR_SEARCH = "starTitle";
|
|
||||||
public static final String OFFLINE_STAR_SETTING = "starSetting";
|
|
||||||
|
|
||||||
public static final String CACHE_KEY_IGNORE = "ignoreArticles";
|
public static final String CACHE_KEY_IGNORE = "ignoreArticles";
|
||||||
public static final String CACHE_AUDIO_SESSION_ID = "audioSessionId";
|
public static final String CACHE_AUDIO_SESSION_ID = "audioSessionId";
|
||||||
@ -152,21 +136,17 @@ public final class Constants {
|
|||||||
public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState";
|
public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState";
|
||||||
public static final String FRAGMENT_LIST = "fragmentList";
|
public static final String FRAGMENT_LIST = "fragmentList";
|
||||||
public static final String FRAGMENT_LIST2 = "fragmentList2";
|
public static final String FRAGMENT_LIST2 = "fragmentList2";
|
||||||
public static final String FRAGMENT_EXTRA = "fragmentExtra";
|
|
||||||
public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper";
|
public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper";
|
||||||
public static final String FRAGMENT_NAME = "fragmentName";
|
public static final String FRAGMENT_NAME = "fragmentName";
|
||||||
public static final String FRAGMENT_POSITION = "fragmentPosition";
|
public static final String FRAGMENT_POSITION = "fragmentPosition";
|
||||||
|
|
||||||
// Name of the preferences file.
|
// Name of the preferences file.
|
||||||
public static final String PREFERENCES_FILE_NAME = "net.nullsum.audinaut_preferences";
|
public static final String PREFERENCES_FILE_NAME = "net.nullsum.audinaut_preferences";
|
||||||
public static final String OFFLINE_SYNC_NAME = "net.nullsum.audinaut.offline";
|
|
||||||
public static final String OFFLINE_SYNC_DEFAULT = "syncDefaults";
|
|
||||||
|
|
||||||
// Account prefs
|
// Account prefs
|
||||||
public static final String SYNC_ACCOUNT_NAME = "Subsonic Account";
|
public static final String SYNC_ACCOUNT_NAME = "Subsonic Account";
|
||||||
public static final String SYNC_ACCOUNT_TYPE = "Audinaut";
|
public static final String SYNC_ACCOUNT_TYPE = "Audinaut";
|
||||||
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "net.nullsum.audinaut.playlists.provider";
|
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "net.nullsum.audinaut.playlists.provider";
|
||||||
public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = "net.nullsum.audinaut.mostrecent.provider";
|
|
||||||
|
|
||||||
public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE";
|
public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE";
|
||||||
|
|
||||||
|
@ -2,10 +2,6 @@ package net.nullsum.audinaut.util;
|
|||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Deque;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.adapter.SectionAdapter;
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
||||||
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
||||||
@ -14,14 +10,15 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||||||
import net.nullsum.audinaut.view.SongView;
|
import net.nullsum.audinaut.view.SongView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
|
||||||
public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback {
|
public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback {
|
||||||
private static final String TAG = DownloadFileItemHelperCallback.class.getSimpleName();
|
|
||||||
|
|
||||||
private SubsonicFragment fragment;
|
|
||||||
private boolean mainList;
|
|
||||||
|
|
||||||
|
private final SubsonicFragment fragment;
|
||||||
|
private final boolean mainList;
|
||||||
|
private final Deque pendingOperations = new ArrayDeque();
|
||||||
private BackgroundTask pendingTask = null;
|
private BackgroundTask pendingTask = null;
|
||||||
private Deque pendingOperations = new ArrayDeque();
|
|
||||||
|
|
||||||
public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) {
|
public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) {
|
||||||
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
|
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
|
||||||
@ -54,17 +51,18 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadService getDownloadService() {
|
private DownloadService getDownloadService() {
|
||||||
return fragment.getDownloadService();
|
return fragment.getDownloadService();
|
||||||
}
|
}
|
||||||
public SectionAdapter getSectionAdapter() {
|
|
||||||
|
private SectionAdapter getSectionAdapter() {
|
||||||
return fragment.getCurrentAdapter();
|
return fragment.getCurrentAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDownloadService() {
|
private void updateDownloadService() {
|
||||||
if(pendingTask == null) {
|
if (pendingTask == null) {
|
||||||
final DownloadService downloadService = getDownloadService();
|
final DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService == null) {
|
if (downloadService == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,21 +70,21 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
boolean running = true;
|
boolean running = true;
|
||||||
while(running) {
|
while (running) {
|
||||||
Object nextOperation = null;
|
Object nextOperation = null;
|
||||||
synchronized (pendingOperations) {
|
synchronized (pendingOperations) {
|
||||||
if(!pendingOperations.isEmpty()) {
|
if (!pendingOperations.isEmpty()) {
|
||||||
nextOperation = pendingOperations.remove();
|
nextOperation = pendingOperations.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextOperation != null) {
|
if (nextOperation != null) {
|
||||||
if(nextOperation instanceof Pair) {
|
if (nextOperation instanceof Pair) {
|
||||||
Pair<Integer, Integer> swap = (Pair) nextOperation;
|
Pair<Integer, Integer> swap = (Pair) nextOperation;
|
||||||
downloadService.swap(mainList, swap.getFirst(), swap.getSecond());
|
downloadService.swap(mainList, swap.getFirst(), swap.getSecond());
|
||||||
} else if(nextOperation instanceof DownloadFile) {
|
} else if (nextOperation instanceof DownloadFile) {
|
||||||
DownloadFile downloadFile = (DownloadFile) nextOperation;
|
DownloadFile downloadFile = (DownloadFile) nextOperation;
|
||||||
if(mainList) {
|
if (mainList) {
|
||||||
downloadService.remove(downloadFile);
|
downloadService.remove(downloadFile);
|
||||||
} else {
|
} else {
|
||||||
downloadService.removeBackground(downloadFile);
|
downloadService.removeBackground(downloadFile);
|
||||||
@ -101,7 +99,7 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba
|
|||||||
pendingTask = null;
|
pendingTask = null;
|
||||||
|
|
||||||
// Start a task if this is non-empty. Means someone added while we were running operations
|
// Start a task if this is non-empty. Means someone added while we were running operations
|
||||||
if(!pendingOperations.isEmpty()) {
|
if (!pendingOperations.isEmpty()) {
|
||||||
updateDownloadService();
|
updateDownloadService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,48 +21,46 @@ import android.content.res.TypedArray;
|
|||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.annotation.AttrRes;
|
import android.support.annotation.AttrRes;
|
||||||
import android.support.annotation.ColorRes;
|
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
|
||||||
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
|
||||||
|
|
||||||
public class DrawableTint {
|
public class DrawableTint {
|
||||||
private static final Map<Integer, Integer> attrMap = new HashMap<>();
|
private static final Map<Integer, Integer> attrMap = new HashMap<>();
|
||||||
private static final WeakHashMap<Integer, Drawable> tintedDrawables = new WeakHashMap<>();
|
private static final WeakHashMap<Integer, Drawable> tintedDrawables = new WeakHashMap<>();
|
||||||
|
|
||||||
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes) {
|
public static Drawable getTintedDrawable(Context context) {
|
||||||
return getTintedDrawable(context, drawableRes, R.attr.colorAccent);
|
if (tintedDrawables.containsKey(R.drawable.ic_toggle_played)) {
|
||||||
}
|
return tintedDrawables.get(R.drawable.ic_toggle_played);
|
||||||
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes, @AttrRes int colorAttr) {
|
|
||||||
if(tintedDrawables.containsKey(drawableRes)) {
|
|
||||||
return tintedDrawables.get(drawableRes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int color = getColorRes(context, colorAttr);
|
int color = getColorRes(context, R.attr.colorAccent);
|
||||||
Drawable background = context.getResources().getDrawable(drawableRes);
|
Drawable background = context.getResources().getDrawable(R.drawable.ic_toggle_played);
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||||
tintedDrawables.put(drawableRes, background);
|
tintedDrawables.put(R.drawable.ic_toggle_played, background);
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
public static Drawable getTintedDrawableFromColor(Context context, @DrawableRes int drawableRes, @ColorRes int colorRes) {
|
|
||||||
if(tintedDrawables.containsKey(drawableRes)) {
|
public static Drawable getTintedDrawableFromColor(Context context) {
|
||||||
return tintedDrawables.get(drawableRes);
|
if (tintedDrawables.containsKey(R.drawable.abc_spinner_mtrl_am_alpha)) {
|
||||||
|
return tintedDrawables.get(R.drawable.abc_spinner_mtrl_am_alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
int color = context.getResources().getColor(colorRes);
|
int color = context.getResources().getColor(android.R.color.white);
|
||||||
Drawable background = context.getResources().getDrawable(drawableRes);
|
Drawable background = context.getResources().getDrawable(R.drawable.abc_spinner_mtrl_am_alpha);
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||||
tintedDrawables.put(drawableRes, background);
|
tintedDrawables.put(R.drawable.abc_spinner_mtrl_am_alpha, background);
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getColorRes(Context context, @AttrRes int colorAttr) {
|
public static int getColorRes(Context context, @AttrRes int colorAttr) {
|
||||||
int color;
|
int color;
|
||||||
if(attrMap.containsKey(colorAttr)) {
|
if (attrMap.containsKey(colorAttr)) {
|
||||||
color = attrMap.get(colorAttr);
|
color = attrMap.get(colorAttr);
|
||||||
} else {
|
} else {
|
||||||
TypedValue typedValue = new TypedValue();
|
TypedValue typedValue = new TypedValue();
|
||||||
@ -74,8 +72,9 @@ public class DrawableTint {
|
|||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDrawableRes(Context context, @AttrRes int drawableAttr) {
|
public static int getDrawableRes(Context context, @AttrRes int drawableAttr) {
|
||||||
if(attrMap.containsKey(drawableAttr)) {
|
if (attrMap.containsKey(drawableAttr)) {
|
||||||
return attrMap.get(drawableAttr);
|
return attrMap.get(drawableAttr);
|
||||||
} else {
|
} else {
|
||||||
int[] attrs = new int[]{drawableAttr};
|
int[] attrs = new int[]{drawableAttr};
|
||||||
@ -86,14 +85,6 @@ public class DrawableTint {
|
|||||||
return drawableRes;
|
return drawableRes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Drawable getTintedAttrDrawable(Context context, @AttrRes int drawableAttr, @AttrRes int colorAttr) {
|
|
||||||
if(tintedDrawables.containsKey(drawableAttr)) {
|
|
||||||
return getTintedDrawable(context, attrMap.get(drawableAttr), colorAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DrawableRes int drawableRes = getDrawableRes(context, drawableAttr);
|
|
||||||
return getTintedDrawable(context, drawableRes, colorAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void wipeTintCache() {
|
public static void wipeTintCache() {
|
||||||
attrMap.clear();
|
attrMap.clear();
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Subsonic.
|
|
||||||
Subsonic 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.
|
|
||||||
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
Copyright 2016 (C) Scott Jackson
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
|
||||||
|
|
||||||
public final class EnvironmentVariables {
|
|
||||||
public static final String PASTEBIN_DEV_KEY = "";
|
|
||||||
}
|
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -23,18 +25,9 @@ import java.io.OutputStream;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.util.ServerProxy;
|
|
||||||
|
|
||||||
public class FileProxy extends ServerProxy {
|
public class FileProxy extends ServerProxy {
|
||||||
private static final String TAG = FileProxy.class.getSimpleName();
|
private static final String TAG = FileProxy.class.getSimpleName();
|
||||||
|
|
||||||
public FileProxy(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ProxyTask getTask(Socket client) {
|
protected ProxyTask getTask(Socket client) {
|
||||||
return new StreamFileTask(client);
|
return new StreamFileTask(client);
|
||||||
}
|
}
|
||||||
@ -48,7 +41,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processRequest() {
|
public boolean processRequest() {
|
||||||
if(!super.processRequest()) {
|
if (!super.processRequest()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +53,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to not try to read past where the file is downloaded
|
// Make sure to not try to read past where the file is downloaded
|
||||||
if(cbSkip != 0 && cbSkip >= file.length()) {
|
return !(cbSkip != 0 && cbSkip >= file.length());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File getFile(String path) {
|
File getFile(String path) {
|
||||||
@ -74,6 +63,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
Long getContentLength() {
|
Long getContentLength() {
|
||||||
return file.length();
|
return file.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
long getFileSize() {
|
long getFileSize() {
|
||||||
return file.length();
|
return file.length();
|
||||||
}
|
}
|
||||||
@ -84,12 +74,12 @@ public class FileProxy extends ServerProxy {
|
|||||||
|
|
||||||
// Create HTTP header
|
// Create HTTP header
|
||||||
String headers;
|
String headers;
|
||||||
if(cbSkip == 0) {
|
if (cbSkip == 0) {
|
||||||
headers = "HTTP/1.0 200 OK\r\n";
|
headers = "HTTP/1.0 200 OK\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers = "HTTP/1.0 206 OK\r\n";
|
headers = "HTTP/1.0 206 OK\r\n";
|
||||||
headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/";
|
headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/";
|
||||||
if(contentLength == null) {
|
if (contentLength == null) {
|
||||||
headers += "*";
|
headers += "*";
|
||||||
} else {
|
} else {
|
||||||
headers += contentLength;
|
headers += contentLength;
|
||||||
@ -102,21 +92,21 @@ public class FileProxy extends ServerProxy {
|
|||||||
String name = file.getPath();
|
String name = file.getPath();
|
||||||
int index = name.lastIndexOf('.');
|
int index = name.lastIndexOf('.');
|
||||||
String ext = "";
|
String ext = "";
|
||||||
if(index != -1) {
|
if (index != -1) {
|
||||||
ext = name.substring(index + 1).toLowerCase();
|
ext = name.substring(index + 1).toLowerCase();
|
||||||
}
|
}
|
||||||
if("mp3".equals(ext)) {
|
if ("mp3".equals(ext)) {
|
||||||
headers += "Content-Type: audio/mpeg\r\n";
|
headers += "Content-Type: audio/mpeg\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
|
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
long fileSize;
|
long fileSize;
|
||||||
if(contentLength == null) {
|
if (contentLength == null) {
|
||||||
fileSize = getFileSize();
|
fileSize = getFileSize();
|
||||||
} else {
|
} else {
|
||||||
fileSize = contentLength;
|
fileSize = contentLength;
|
||||||
if(cbSkip > 0) {
|
if (cbSkip > 0) {
|
||||||
headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n";
|
headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers += "Content-Length: " + fileSize + "\r\n";
|
headers += "Content-Length: " + fileSize + "\r\n";
|
||||||
@ -132,7 +122,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
OutputStream output = null;
|
OutputStream output = null;
|
||||||
byte[] buff = new byte[64 * 1024];
|
byte[] buff = new byte[64 * 1024];
|
||||||
try {
|
try {
|
||||||
output = new BufferedOutputStream(client.getOutputStream(), 32*1024);
|
output = new BufferedOutputStream(client.getOutputStream(), 32 * 1024);
|
||||||
output.write(headers.getBytes());
|
output.write(headers.getBytes());
|
||||||
|
|
||||||
// Make sure to have file lock
|
// Make sure to have file lock
|
||||||
@ -165,7 +155,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Done regardless of whether or not it thinks it is
|
// Done regardless of whether or not it thinks it is
|
||||||
if(isWorkDone()) {
|
if (isWorkDone()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,14 +168,12 @@ public class FileProxy extends ServerProxy {
|
|||||||
|
|
||||||
// Release file lock, use of stream proxy means nothing else is using it
|
// Release file lock, use of stream proxy means nothing else is using it
|
||||||
onStop();
|
onStop();
|
||||||
}
|
} catch (SocketException socketException) {
|
||||||
catch (SocketException socketException) {
|
|
||||||
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
|
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
|
||||||
|
|
||||||
// Release file lock, use of stream proxy means nothing else is using it
|
// Release file lock, use of stream proxy means nothing else is using it
|
||||||
onStop();
|
onStop();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
Log.e(TAG, "Exception thrown from streaming task:");
|
Log.e(TAG, "Exception thrown from streaming task:");
|
||||||
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
@ -196,8 +184,7 @@ public class FileProxy extends ServerProxy {
|
|||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
|
||||||
Log.e(TAG, "IOException while cleaning up streaming task:");
|
Log.e(TAG, "IOException while cleaning up streaming task:");
|
||||||
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
@ -206,12 +193,15 @@ public class FileProxy extends ServerProxy {
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWorkDone() {
|
public boolean isWorkDone() {
|
||||||
return cbSkip >= file.length();
|
return cbSkip >= file.length();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,26 @@
|
|||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
|
|
||||||
|
import net.nullsum.audinaut.domain.Artist;
|
||||||
|
import net.nullsum.audinaut.domain.Genre;
|
||||||
|
import net.nullsum.audinaut.domain.Indexes;
|
||||||
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
|
import net.nullsum.audinaut.domain.MusicFolder;
|
||||||
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
|
import net.nullsum.audinaut.service.MediaStoreService;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -28,34 +48,16 @@ import java.io.IOException;
|
|||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
import java.util.zip.DeflaterOutputStream;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.util.Log;
|
|
||||||
import net.nullsum.audinaut.domain.Artist;
|
|
||||||
import net.nullsum.audinaut.domain.Genre;
|
|
||||||
import net.nullsum.audinaut.domain.Indexes;
|
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
||||||
import net.nullsum.audinaut.domain.MusicFolder;
|
|
||||||
import net.nullsum.audinaut.service.MediaStoreService;
|
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
@ -65,10 +67,10 @@ public class FileUtil {
|
|||||||
private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
|
private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
|
||||||
private static final String[] FILE_SYSTEM_UNSAFE_DIR = {"\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
|
private static final String[] FILE_SYSTEM_UNSAFE_DIR = {"\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
|
||||||
private static final List<String> MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma");
|
private static final List<String> MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma");
|
||||||
private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u");
|
private static final List<String> PLAYLIST_FILE_EXTENSIONS = Collections.singletonList("m3u");
|
||||||
private static final int MAX_FILENAME_LENGTH = 254 - ".complete.mp3".length();
|
private static final int MAX_FILENAME_LENGTH = 254 - ".complete.mp3".length();
|
||||||
private static File DEFAULT_MUSIC_DIR;
|
|
||||||
private static final Kryo kryo = new Kryo();
|
private static final Kryo kryo = new Kryo();
|
||||||
|
private static File DEFAULT_MUSIC_DIR;
|
||||||
private static HashMap<String, MusicDirectory.Entry> entryLookup;
|
private static HashMap<String, MusicDirectory.Entry> entryLookup;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -80,27 +82,8 @@ public class FileUtil {
|
|||||||
kryo.register(Genre.class);
|
kryo.register(Genre.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getAnySong(Context context) {
|
|
||||||
File dir = getMusicDirectory(context);
|
|
||||||
return getAnySong(context, dir);
|
|
||||||
}
|
|
||||||
private static File getAnySong(Context context, File dir) {
|
|
||||||
for(File file: dir.listFiles()) {
|
|
||||||
if(file.isDirectory()) {
|
|
||||||
return getAnySong(context, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
String extension = getExtension(file.getName());
|
|
||||||
if(MUSIC_FILE_EXTENSIONS.contains(extension)) {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getEntryFile(Context context, MusicDirectory.Entry entry) {
|
public static File getEntryFile(Context context, MusicDirectory.Entry entry) {
|
||||||
if(entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
return getAlbumDirectory(context, entry);
|
return getAlbumDirectory(context, entry);
|
||||||
} else {
|
} else {
|
||||||
return getSongFile(context, entry);
|
return getSongFile(context, entry);
|
||||||
@ -120,7 +103,7 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileName.append(fileSystemSafe(song.getTitle()));
|
fileName.append(fileSystemSafe(song.getTitle()));
|
||||||
if(fileName.length() >= MAX_FILENAME_LENGTH) {
|
if (fileName.length() >= MAX_FILENAME_LENGTH) {
|
||||||
fileName.setLength(MAX_FILENAME_LENGTH);
|
fileName.setLength(MAX_FILENAME_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +121,7 @@ public class FileUtil {
|
|||||||
File playlistDir = getPlaylistDirectory(context, server);
|
File playlistDir = getPlaylistDirectory(context, server);
|
||||||
return new File(playlistDir, fileSystemSafe(name) + ".m3u");
|
return new File(playlistDir, fileSystemSafe(name) + ".m3u");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writePlaylistFile(Context context, File file, MusicDirectory playlist) throws IOException {
|
public static void writePlaylistFile(Context context, File file, MusicDirectory playlist) throws IOException {
|
||||||
FileWriter fw = new FileWriter(file);
|
FileWriter fw = new FileWriter(file);
|
||||||
BufferedWriter bw = new BufferedWriter(fw);
|
BufferedWriter bw = new BufferedWriter(fw);
|
||||||
@ -145,25 +129,27 @@ public class FileUtil {
|
|||||||
fw.write("#EXTM3U\n");
|
fw.write("#EXTM3U\n");
|
||||||
for (MusicDirectory.Entry e : playlist.getChildren()) {
|
for (MusicDirectory.Entry e : playlist.getChildren()) {
|
||||||
String filePath = FileUtil.getSongFile(context, e).getAbsolutePath();
|
String filePath = FileUtil.getSongFile(context, e).getAbsolutePath();
|
||||||
if(! new File(filePath).exists()){
|
if (!new File(filePath).exists()) {
|
||||||
String ext = FileUtil.getExtension(filePath);
|
String ext = FileUtil.getExtension(filePath);
|
||||||
String base = FileUtil.getBaseName(filePath);
|
String base = FileUtil.getBaseName(filePath);
|
||||||
filePath = base + ".complete." + ext;
|
filePath = base + ".complete." + ext;
|
||||||
}
|
}
|
||||||
fw.write(filePath + "\n");
|
fw.write(filePath + "\n");
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to save playlist: " + playlist.getName());
|
Log.w(TAG, "Failed to save playlist: " + playlist.getName());
|
||||||
} finally {
|
} finally {
|
||||||
bw.close();
|
bw.close();
|
||||||
fw.close();
|
fw.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getPlaylistDirectory(Context context) {
|
public static File getPlaylistDirectory(Context context) {
|
||||||
File playlistDir = new File(getSubsonicDirectory(context), "playlists");
|
File playlistDir = new File(getSubsonicDirectory(context), "playlists");
|
||||||
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
||||||
return playlistDir;
|
return playlistDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getPlaylistDirectory(Context context, String server) {
|
public static File getPlaylistDirectory(Context context, String server) {
|
||||||
File playlistDir = new File(getPlaylistDirectory(context), server);
|
File playlistDir = new File(getPlaylistDirectory(context), server);
|
||||||
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
||||||
@ -171,9 +157,9 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static File getAlbumArtFile(Context context, MusicDirectory.Entry entry) {
|
public static File getAlbumArtFile(Context context, MusicDirectory.Entry entry) {
|
||||||
if(entry.getId().indexOf(ImageLoader.PLAYLIST_PREFIX) != -1) {
|
if (entry.getId().contains(ImageLoader.PLAYLIST_PREFIX)) {
|
||||||
File dir = getAlbumArtDirectory(context);
|
File dir = getAlbumArtDirectory(context);
|
||||||
return new File(dir, Util.md5Hex(ImageLoader.PLAYLIST_PREFIX + entry.getTitle()) + ".jpeg");
|
return new File(dir, Util.md5Hex(ImageLoader.PLAYLIST_PREFIX + entry.getTitle()) + ".jpeg");
|
||||||
} else {
|
} else {
|
||||||
File albumDir = getAlbumDirectory(context, entry);
|
File albumDir = getAlbumDirectory(context, entry);
|
||||||
File artFile;
|
File artFile;
|
||||||
@ -191,10 +177,11 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getAlbumArtFile(File albumDir) {
|
private static File getAlbumArtFile(File albumDir) {
|
||||||
return new File(albumDir, Constants.ALBUM_ART_FILE);
|
return new File(albumDir, Constants.ALBUM_ART_FILE);
|
||||||
}
|
}
|
||||||
public static File getHexAlbumArtFile(Context context, File albumDir) {
|
|
||||||
|
private static File getHexAlbumArtFile(Context context, File albumDir) {
|
||||||
return new File(getAlbumArtDirectory(context), Util.md5Hex(albumDir.getPath()) + ".jpeg");
|
return new File(getAlbumArtDirectory(context), Util.md5Hex(albumDir.getPath()) + ".jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,25 +201,7 @@ public class FileUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getMiscDirectory(Context context) {
|
|
||||||
File dir = new File(getSubsonicDirectory(context), "misc");
|
|
||||||
ensureDirectoryExistsAndIsReadWritable(dir);
|
|
||||||
ensureDirectoryExistsAndIsReadWritable(new File(dir, ".nomedia"));
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getMiscFile(Context context, String url) {
|
|
||||||
return new File(getMiscDirectory(context), Util.md5Hex(url) + ".jpeg");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap getMiscBitmap(Context context, String url, int size) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap getSampledBitmap(byte[] bytes, int size) {
|
public static Bitmap getSampledBitmap(byte[] bytes, int size) {
|
||||||
return getSampledBitmap(bytes, size, true);
|
|
||||||
}
|
|
||||||
public static Bitmap getSampledBitmap(byte[] bytes, int size, boolean allowUnscaled) {
|
|
||||||
final BitmapFactory.Options opt = new BitmapFactory.Options();
|
final BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||||
opt.inJustDecodeBounds = true;
|
opt.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
|
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
|
||||||
@ -240,19 +209,17 @@ public class FileUtil {
|
|||||||
opt.inSampleSize = Util.calculateInSampleSize(opt, size, Util.getScaledHeight(opt.outHeight, opt.outWidth, size));
|
opt.inSampleSize = Util.calculateInSampleSize(opt, size, Util.getScaledHeight(opt.outHeight, opt.outWidth, size));
|
||||||
opt.inJustDecodeBounds = false;
|
opt.inJustDecodeBounds = false;
|
||||||
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
|
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
|
||||||
if(bitmap == null) {
|
if (bitmap == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return getScaledBitmap(bitmap, size, allowUnscaled);
|
return getScaledBitmap(bitmap, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Bitmap getScaledBitmap(Bitmap bitmap, int size) {
|
|
||||||
return getScaledBitmap(bitmap, size, true);
|
private static Bitmap getScaledBitmap(Bitmap bitmap, int size) {
|
||||||
}
|
|
||||||
public static Bitmap getScaledBitmap(Bitmap bitmap, int size, boolean allowUnscaled) {
|
|
||||||
// Don't waste time scaling if the difference is minor
|
// Don't waste time scaling if the difference is minor
|
||||||
// Large album arts still need to be scaled since displayed as is on now playing!
|
// Large album arts still need to be scaled since displayed as is on now playing!
|
||||||
if(allowUnscaled && size < 400 && bitmap.getWidth() < (size * 1.1)) {
|
if (size < 400 && bitmap.getWidth() < (size * 1.1)) {
|
||||||
return bitmap;
|
return bitmap;
|
||||||
} else {
|
} else {
|
||||||
return Bitmap.createScaledBitmap(bitmap, size, Util.getScaledHeight(bitmap, size), true);
|
return Bitmap.createScaledBitmap(bitmap, size, Util.getScaledHeight(bitmap, size), true);
|
||||||
@ -267,12 +234,11 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static File getArtistDirectory(Context context, Artist artist) {
|
public static File getArtistDirectory(Context context, Artist artist) {
|
||||||
File dir = new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName()));
|
return new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName()));
|
||||||
return dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getArtistDirectory(Context context, MusicDirectory.Entry artist) {
|
public static File getArtistDirectory(Context context, MusicDirectory.Entry artist) {
|
||||||
File dir = new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getTitle()));
|
return new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getTitle()));
|
||||||
return dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getAlbumDirectory(Context context, MusicDirectory.Entry entry) {
|
public static File getAlbumDirectory(Context context, MusicDirectory.Entry entry) {
|
||||||
@ -280,26 +246,26 @@ public class FileUtil {
|
|||||||
if (entry.getPath() != null) {
|
if (entry.getPath() != null) {
|
||||||
File f = new File(fileSystemSafeDir(entry.getPath()));
|
File f = new File(fileSystemSafeDir(entry.getPath()));
|
||||||
String folder = getMusicDirectory(context).getPath();
|
String folder = getMusicDirectory(context).getPath();
|
||||||
if(entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
folder += "/" + f.getPath();
|
folder += "/" + f.getPath();
|
||||||
} else if(f.getParent() != null) {
|
} else if (f.getParent() != null) {
|
||||||
folder += "/" + f.getParent();
|
folder += "/" + f.getParent();
|
||||||
}
|
}
|
||||||
dir = new File(folder);
|
dir = new File(folder);
|
||||||
} else {
|
} else {
|
||||||
MusicDirectory.Entry firstSong;
|
MusicDirectory.Entry firstSong;
|
||||||
if(!Util.isOffline(context)) {
|
if (!Util.isOffline(context)) {
|
||||||
firstSong = lookupChild(context, entry, false);
|
firstSong = lookupChild(context, entry, false);
|
||||||
if(firstSong != null) {
|
if (firstSong != null) {
|
||||||
File songFile = FileUtil.getSongFile(context, firstSong);
|
File songFile = FileUtil.getSongFile(context, firstSong);
|
||||||
dir = songFile.getParentFile();
|
dir = songFile.getParentFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dir == null) {
|
if (dir == null) {
|
||||||
String artist = fileSystemSafe(entry.getArtist());
|
String artist = fileSystemSafe(entry.getArtist());
|
||||||
String album = fileSystemSafe(entry.getAlbum());
|
String album = fileSystemSafe(entry.getAlbum());
|
||||||
if("unnamed".equals(album)) {
|
if ("unnamed".equals(album)) {
|
||||||
album = fileSystemSafe(entry.getTitle());
|
album = fileSystemSafe(entry.getTitle());
|
||||||
}
|
}
|
||||||
dir = new File(getMusicDirectory(context).getPath() + "/" + artist + "/" + album);
|
dir = new File(getMusicDirectory(context).getPath() + "/" + artist + "/" + album);
|
||||||
@ -310,30 +276,30 @@ public class FileUtil {
|
|||||||
|
|
||||||
public static MusicDirectory.Entry lookupChild(Context context, MusicDirectory.Entry entry, boolean allowDir) {
|
public static MusicDirectory.Entry lookupChild(Context context, MusicDirectory.Entry entry, boolean allowDir) {
|
||||||
// Initialize lookupMap if first time called
|
// Initialize lookupMap if first time called
|
||||||
String lookupName = Util.getCacheName(context, "entryLookup");
|
String lookupName = Util.getCacheName(context);
|
||||||
if(entryLookup == null) {
|
if (entryLookup == null) {
|
||||||
entryLookup = deserialize(context, lookupName, HashMap.class);
|
entryLookup = deserialize(context, lookupName, HashMap.class);
|
||||||
|
|
||||||
// Create it if
|
// Create it if
|
||||||
if(entryLookup == null) {
|
if (entryLookup == null) {
|
||||||
entryLookup = new HashMap<String, MusicDirectory.Entry>();
|
entryLookup = new HashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this lookup has already been done before
|
// Check if this lookup has already been done before
|
||||||
MusicDirectory.Entry child = entryLookup.get(entry.getId());
|
MusicDirectory.Entry child = entryLookup.get(entry.getId());
|
||||||
if(child != null) {
|
if (child != null) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a special lookup since 4.7+ doesn't match artist/album to entry.getPath
|
// Do a special lookup since 4.7+ doesn't match artist/album to entry.getPath
|
||||||
String s = Util.getRestUrl(context, null, false) + entry.getId();
|
String s = Util.getRestUrl(context, null, false) + entry.getId();
|
||||||
String cacheName = (Util.isTagBrowsing(context) ? "album-" : "directory-") + s.hashCode() + ".ser";
|
String cacheName = "album-" + s.hashCode() + ".ser";
|
||||||
MusicDirectory entryDir = FileUtil.deserialize(context, cacheName, MusicDirectory.class);
|
MusicDirectory entryDir = FileUtil.deserialize(context, cacheName, MusicDirectory.class);
|
||||||
|
|
||||||
if(entryDir != null) {
|
if (entryDir != null) {
|
||||||
List<MusicDirectory.Entry> songs = entryDir.getChildren(allowDir, true);
|
List<MusicDirectory.Entry> songs = entryDir.getChildren(allowDir, true);
|
||||||
if(songs.size() > 0) {
|
if (songs.size() > 0) {
|
||||||
child = songs.get(0);
|
child = songs.get(0);
|
||||||
entryLookup.put(entry.getId(), child);
|
entryLookup.put(entry.getId(), child);
|
||||||
serialize(context, entryLookup, lookupName);
|
serialize(context, entryLookup, lookupName);
|
||||||
@ -353,22 +319,14 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File createDirectory(Context context, String name) {
|
|
||||||
File dir = new File(getSubsonicDirectory(context), name);
|
|
||||||
if (!dir.exists() && !dir.mkdirs()) {
|
|
||||||
Log.e(TAG, "Failed to create " + name);
|
|
||||||
}
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getSubsonicDirectory(Context context) {
|
public static File getSubsonicDirectory(Context context) {
|
||||||
return context.getExternalFilesDir(null);
|
return context.getExternalFilesDir(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getDefaultMusicDirectory(Context context) {
|
public static File getDefaultMusicDirectory(Context context) {
|
||||||
if(DEFAULT_MUSIC_DIR == null) {
|
if (DEFAULT_MUSIC_DIR == null) {
|
||||||
File[] dirs;
|
File[] dirs;
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
dirs = context.getExternalMediaDirs();
|
dirs = context.getExternalMediaDirs();
|
||||||
} else {
|
} else {
|
||||||
dirs = ContextCompat.getExternalFilesDirs(context, null);
|
dirs = ContextCompat.getExternalFilesDirs(context, null);
|
||||||
@ -380,7 +338,7 @@ public class FileUtil {
|
|||||||
Log.e(TAG, "Failed to create default dir " + DEFAULT_MUSIC_DIR);
|
Log.e(TAG, "Failed to create default dir " + DEFAULT_MUSIC_DIR);
|
||||||
|
|
||||||
// Some devices seem to have screwed up the new media directory API. Go figure. Try again with standard locations
|
// Some devices seem to have screwed up the new media directory API. Go figure. Try again with standard locations
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
dirs = ContextCompat.getExternalFilesDirs(context, null);
|
dirs = ContextCompat.getExternalFilesDirs(context, null);
|
||||||
|
|
||||||
DEFAULT_MUSIC_DIR = new File(getBestDir(dirs), "music");
|
DEFAULT_MUSIC_DIR = new File(getBestDir(dirs), "music");
|
||||||
@ -395,13 +353,14 @@ public class FileUtil {
|
|||||||
|
|
||||||
return DEFAULT_MUSIC_DIR;
|
return DEFAULT_MUSIC_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File getBestDir(File[] dirs) {
|
private static File getBestDir(File[] dirs) {
|
||||||
// Past 5.0 we can query directly for SD Card
|
// Past 5.0 we can query directly for SD Card
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
for(int i = 0; i < dirs.length; i++) {
|
for (File dir : dirs) {
|
||||||
try {
|
try {
|
||||||
if (dirs[i] != null && Environment.isExternalStorageRemovable(dirs[i])) {
|
if (dir != null && Environment.isExternalStorageRemovable(dir)) {
|
||||||
return dirs[i];
|
return dir;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to check if is external", e);
|
Log.e(TAG, "Failed to check if is external", e);
|
||||||
@ -410,8 +369,8 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Before 5.0, we have to guess. Most of the time the SD card is last
|
// Before 5.0, we have to guess. Most of the time the SD card is last
|
||||||
for(int i = dirs.length - 1; i >= 0; i--) {
|
for (int i = dirs.length - 1; i >= 0; i--) {
|
||||||
if(dirs[i] != null) {
|
if (dirs[i] != null) {
|
||||||
return dirs[i];
|
return dirs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,38 +384,43 @@ public class FileUtil {
|
|||||||
File dir = new File(path);
|
File dir = new File(path);
|
||||||
return ensureDirectoryExistsAndIsReadWritable(dir) ? dir : getDefaultMusicDirectory(context);
|
return ensureDirectoryExistsAndIsReadWritable(dir) ? dir : getDefaultMusicDirectory(context);
|
||||||
}
|
}
|
||||||
public static boolean deleteMusicDirectory(Context context) {
|
|
||||||
|
public static void deleteMusicDirectory(Context context) {
|
||||||
File musicDirectory = FileUtil.getMusicDirectory(context);
|
File musicDirectory = FileUtil.getMusicDirectory(context);
|
||||||
MediaStoreService mediaStore = new MediaStoreService(context);
|
MediaStoreService mediaStore = new MediaStoreService(context);
|
||||||
return recursiveDelete(musicDirectory, mediaStore);
|
recursiveDelete(musicDirectory, mediaStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteSerializedCache(Context context) {
|
public static void deleteSerializedCache(Context context) {
|
||||||
for(File file: context.getCacheDir().listFiles()) {
|
for (File file : context.getCacheDir().listFiles()) {
|
||||||
if(file.getName().indexOf(".ser") != -1) {
|
if (file.getName().contains(".ser")) {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static boolean deleteArtworkCache(Context context) {
|
|
||||||
|
public static void deleteArtworkCache(Context context) {
|
||||||
File artDirectory = FileUtil.getAlbumArtDirectory(context);
|
File artDirectory = FileUtil.getAlbumArtDirectory(context);
|
||||||
return recursiveDelete(artDirectory);
|
recursiveDelete(artDirectory);
|
||||||
}
|
}
|
||||||
public static boolean recursiveDelete(File dir) {
|
|
||||||
return recursiveDelete(dir, null);
|
private static void recursiveDelete(File dir) {
|
||||||
|
recursiveDelete(dir, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean recursiveDelete(File dir, MediaStoreService mediaStore) {
|
public static boolean recursiveDelete(File dir, MediaStoreService mediaStore) {
|
||||||
if (dir != null && dir.exists()) {
|
if (dir != null && dir.exists()) {
|
||||||
File[] list = dir.listFiles();
|
File[] list = dir.listFiles();
|
||||||
if(list != null) {
|
if (list != null) {
|
||||||
for(File file: list) {
|
for (File file : list) {
|
||||||
if(file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
if(!recursiveDelete(file, mediaStore)) {
|
if (!recursiveDelete(file, mediaStore)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if(file.exists()) {
|
} else if (file.exists()) {
|
||||||
if(!file.delete()) {
|
if (!file.delete()) {
|
||||||
return false;
|
return false;
|
||||||
} else if(mediaStore != null) {
|
} else if (mediaStore != null) {
|
||||||
mediaStore.deleteFromMediaStore(file);
|
mediaStore.deleteFromMediaStore(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,7 +434,7 @@ public class FileUtil {
|
|||||||
public static void deleteEmptyDir(File dir) {
|
public static void deleteEmptyDir(File dir) {
|
||||||
try {
|
try {
|
||||||
File[] children = dir.listFiles();
|
File[] children = dir.listFiles();
|
||||||
if(children == null) {
|
if (children == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,33 +448,12 @@ public class FileUtil {
|
|||||||
if (children.length == 0) {
|
if (children.length == 0) {
|
||||||
Util.delete(dir);
|
Util.delete(dir);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error while trying to delete empty dir", e);
|
Log.w(TAG, "Error while trying to delete empty dir", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unpinSong(Context context, File saveFile) {
|
private static boolean ensureDirectoryExistsAndIsReadWritable(File dir) {
|
||||||
// Don't try to unpin a song which isn't actually pinned
|
|
||||||
if(saveFile.getName().contains(".complete")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unpin file, rename to .complete
|
|
||||||
File completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) +
|
|
||||||
".complete." + FileUtil.getExtension(saveFile.getName()));
|
|
||||||
|
|
||||||
if(!saveFile.renameTo(completeFile)) {
|
|
||||||
Log.w(TAG, "Failed to upin " + saveFile + " to " + completeFile);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
new MediaStoreService(context).renameInMediaStore(completeFile, saveFile);
|
|
||||||
} catch(Exception e) {
|
|
||||||
Log.w(TAG, "Failed to write to media store");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean ensureDirectoryExistsAndIsReadWritable(File dir) {
|
|
||||||
if (dir == null) {
|
if (dir == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -540,13 +483,14 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyCanWrite(File dir) {
|
public static boolean verifyCanWrite(File dir) {
|
||||||
if(ensureDirectoryExistsAndIsReadWritable(dir)) {
|
if (ensureDirectoryExistsAndIsReadWritable(dir)) {
|
||||||
try {
|
try {
|
||||||
File tmp = new File(dir, "checkWrite");
|
File tmp = new File(dir, "checkWrite");
|
||||||
tmp.createNewFile();
|
tmp.createNewFile();
|
||||||
if(tmp.exists()) {
|
if (tmp.exists()) {
|
||||||
if(tmp.delete()) {
|
if (tmp.delete()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Failed to delete temp file, retrying");
|
Log.w(TAG, "Failed to delete temp file, retrying");
|
||||||
@ -554,7 +498,7 @@ public class FileUtil {
|
|||||||
// This should never be reached since this is a file Audinaut created!
|
// This should never be reached since this is a file Audinaut created!
|
||||||
Thread.sleep(100L);
|
Thread.sleep(100L);
|
||||||
tmp = new File(dir, "checkWrite");
|
tmp = new File(dir, "checkWrite");
|
||||||
if(tmp.delete()) {
|
if (tmp.delete()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Failed retry to delete temp file");
|
Log.w(TAG, "Failed retry to delete temp file");
|
||||||
@ -565,7 +509,7 @@ public class FileUtil {
|
|||||||
Log.w(TAG, "Temp file does not actually exist");
|
Log.w(TAG, "Temp file does not actually exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to create tmp file", e);
|
Log.w(TAG, "Failed to create tmp file", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -575,12 +519,12 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a given filename safe by replacing special characters like slashes ("/" and "\")
|
* Makes a given filename safe by replacing special characters like slashes ("/" and "\")
|
||||||
* with dashes ("-").
|
* with dashes ("-").
|
||||||
*
|
*
|
||||||
* @param filename The filename in question.
|
* @param filename The filename in question.
|
||||||
* @return The filename with special characters replaced by hyphens.
|
* @return The filename with special characters replaced by hyphens.
|
||||||
*/
|
*/
|
||||||
private static String fileSystemSafe(String filename) {
|
private static String fileSystemSafe(String filename) {
|
||||||
if (filename == null || filename.trim().length() == 0) {
|
if (filename == null || filename.trim().length() == 0) {
|
||||||
return "unnamed";
|
return "unnamed";
|
||||||
@ -618,10 +562,10 @@ public class FileUtil {
|
|||||||
File[] files = dir.listFiles();
|
File[] files = dir.listFiles();
|
||||||
if (files == null) {
|
if (files == null) {
|
||||||
Log.w(TAG, "Failed to list children for " + dir.getPath());
|
Log.w(TAG, "Failed to list children for " + dir.getPath());
|
||||||
return new TreeSet<File>();
|
return new TreeSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TreeSet<File>(Arrays.asList(files));
|
return new TreeSet<>(Arrays.asList(files));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SortedSet<File> listMediaFiles(File dir) {
|
public static SortedSet<File> listMediaFiles(File dir) {
|
||||||
@ -641,11 +585,6 @@ public class FileUtil {
|
|||||||
return MUSIC_FILE_EXTENSIONS.contains(extension);
|
return MUSIC_FILE_EXTENSIONS.contains(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMusicFile(File file) {
|
|
||||||
String extension = getExtension(file.getName());
|
|
||||||
return MUSIC_FILE_EXTENSIONS.contains(extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPlaylistFile(File file) {
|
public static boolean isPlaylistFile(File file) {
|
||||||
String extension = getExtension(file.getName());
|
String extension = getExtension(file.getName());
|
||||||
return PLAYLIST_FILE_EXTENSIONS.contains(extension);
|
return PLAYLIST_FILE_EXTENSIONS.contains(extension);
|
||||||
@ -675,32 +614,7 @@ public class FileUtil {
|
|||||||
return index == -1 ? name : name.substring(0, index);
|
return index == -1 ? name : name.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Long[] getUsedSize(Context context, File file) {
|
public static <T extends Serializable> void serialize(Context context, T obj, String fileName) {
|
||||||
long number = 0L;
|
|
||||||
long permanent = 0L;
|
|
||||||
long size = 0L;
|
|
||||||
|
|
||||||
if(file.isFile()) {
|
|
||||||
if(isMediaFile(file)) {
|
|
||||||
if(file.getAbsolutePath().indexOf(".complete") == -1) {
|
|
||||||
permanent++;
|
|
||||||
}
|
|
||||||
return new Long[] {1L, permanent, file.length()};
|
|
||||||
} else {
|
|
||||||
return new Long[] {0L, 0L, 0L};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (File child : FileUtil.listFiles(file)) {
|
|
||||||
Long[] pair = getUsedSize(context, child);
|
|
||||||
number += pair[0];
|
|
||||||
permanent += pair[1];
|
|
||||||
size += pair[2];
|
|
||||||
}
|
|
||||||
return new Long[] {number, permanent, size};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Serializable> boolean serialize(Context context, T obj, String fileName) {
|
|
||||||
Output out = null;
|
Output out = null;
|
||||||
try {
|
try {
|
||||||
RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw");
|
RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw");
|
||||||
@ -708,32 +622,26 @@ public class FileUtil {
|
|||||||
synchronized (kryo) {
|
synchronized (kryo) {
|
||||||
kryo.writeObject(out, obj);
|
kryo.writeObject(out, obj);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.w(TAG, "Failed to serialize object to " + fileName);
|
Log.w(TAG, "Failed to serialize object to " + fileName);
|
||||||
return false;
|
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(out);
|
Util.close(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Serializable> T deserialize(Context context, String fileName, Class<T> tClass) {
|
public static <T extends Serializable> T deserialize(Context context, String fileName, Class<T> tClass) {
|
||||||
return deserialize(context, fileName, tClass, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Serializable> T deserialize(Context context, String fileName, Class<T> tClass, int hoursOld) {
|
|
||||||
Input in = null;
|
Input in = null;
|
||||||
try {
|
try {
|
||||||
File file = new File(context.getCacheDir(), fileName);
|
File file = new File(context.getCacheDir(), fileName);
|
||||||
if(!file.exists()) {
|
if (!file.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hoursOld != 0) {
|
if (0 != 0) {
|
||||||
Date fileDate = new Date(file.lastModified());
|
Date fileDate = new Date(file.lastModified());
|
||||||
// Convert into hours
|
// Convert into hours
|
||||||
long age = (new Date().getTime() - fileDate.getTime()) / 1000 / 3600;
|
long age = (new Date().getTime() - fileDate.getTime()) / 1000 / 3600;
|
||||||
if(age > hoursOld) {
|
if (age > 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,10 +650,9 @@ public class FileUtil {
|
|||||||
|
|
||||||
in = new Input(new FileInputStream(randomFile.getFD()));
|
in = new Input(new FileInputStream(randomFile.getFD()));
|
||||||
synchronized (kryo) {
|
synchronized (kryo) {
|
||||||
T result = kryo.readObject(in, tClass);
|
return kryo.readObject(in, tClass);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} catch(FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// Different error message
|
// Different error message
|
||||||
Log.w(TAG, "No serialization for object from " + fileName);
|
Log.w(TAG, "No serialization for object from " + fileName);
|
||||||
return null;
|
return null;
|
||||||
@ -757,7 +664,7 @@ public class FileUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Serializable> boolean serializeCompressed(Context context, T obj, String fileName) {
|
public static <T extends Serializable> void serializeCompressed(Context context, T obj, String fileName) {
|
||||||
Output out = null;
|
Output out = null;
|
||||||
try {
|
try {
|
||||||
RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw");
|
RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw");
|
||||||
@ -765,10 +672,8 @@ public class FileUtil {
|
|||||||
synchronized (kryo) {
|
synchronized (kryo) {
|
||||||
kryo.writeObject(out, obj);
|
kryo.writeObject(out, obj);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.w(TAG, "Failed to serialize compressed object to " + fileName);
|
Log.w(TAG, "Failed to serialize compressed object to " + fileName);
|
||||||
return false;
|
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(out);
|
Util.close(out);
|
||||||
}
|
}
|
||||||
@ -781,10 +686,9 @@ public class FileUtil {
|
|||||||
|
|
||||||
in = new Input(new InflaterInputStream(new FileInputStream(file.getFD())));
|
in = new Input(new InflaterInputStream(new FileInputStream(file.getFD())));
|
||||||
synchronized (kryo) {
|
synchronized (kryo) {
|
||||||
T result = kryo.readObject(in, tClass);
|
return kryo.readObject(in, tClass);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} catch(FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// Different error message
|
// Different error message
|
||||||
Log.w(TAG, "No serialization compressed for object from " + fileName);
|
Log.w(TAG, "No serialization compressed for object from " + fileName);
|
||||||
return null;
|
return null;
|
||||||
|
@ -28,18 +28,15 @@ import android.graphics.Shader;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.TransitionDrawable;
|
import android.graphics.drawable.TransitionDrawable;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.support.v4.util.LruCache;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.support.v4.util.LruCache;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||||
import net.nullsum.audinaut.domain.Playlist;
|
import net.nullsum.audinaut.domain.Playlist;
|
||||||
@ -54,20 +51,18 @@ import net.nullsum.audinaut.service.MusicServiceFactory;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class ImageLoader {
|
public class ImageLoader {
|
||||||
private static final String TAG = ImageLoader.class.getSimpleName();
|
|
||||||
public static final String PLAYLIST_PREFIX = "pl-";
|
public static final String PLAYLIST_PREFIX = "pl-";
|
||||||
|
private static final String TAG = ImageLoader.class.getSimpleName();
|
||||||
private Context context;
|
private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444};
|
||||||
private LruCache<String, Bitmap> cache;
|
|
||||||
private Handler handler;
|
|
||||||
private Bitmap nowPlaying;
|
|
||||||
private Bitmap nowPlayingSmall;
|
|
||||||
private final int imageSizeDefault;
|
private final int imageSizeDefault;
|
||||||
private final int imageSizeLarge;
|
private final int imageSizeLarge;
|
||||||
private boolean clearingCache = false;
|
|
||||||
private final int cacheSize;
|
private final int cacheSize;
|
||||||
|
private final Context context;
|
||||||
private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444};
|
private final Handler handler;
|
||||||
|
private LruCache<String, Bitmap> cache;
|
||||||
|
private Bitmap nowPlaying;
|
||||||
|
private Bitmap nowPlayingSmall;
|
||||||
|
private boolean clearingCache = false;
|
||||||
|
|
||||||
public ImageLoader(Context context) {
|
public ImageLoader(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -88,10 +83,10 @@ public class ImageLoader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
|
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
|
||||||
if(evicted) {
|
if (evicted) {
|
||||||
if((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) {
|
if ((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) {
|
||||||
oldBitmap.recycle();
|
oldBitmap.recycle();
|
||||||
} else if(oldBitmap != newBitmap) {
|
} else if (oldBitmap != newBitmap) {
|
||||||
cache.put(key, oldBitmap);
|
cache.put(key, oldBitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,12 +107,14 @@ public class ImageLoader {
|
|||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLowMemory(float percent) {
|
public void onLowMemory(float percent) {
|
||||||
Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize());
|
Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize());
|
||||||
cache.resize(Math.round(cacheSize * (1 - percent)));
|
cache.resize(Math.round(cacheSize * (1 - percent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUIVisible() {
|
public void onUIVisible() {
|
||||||
if(cache.maxSize() != cacheSize) {
|
if (cache.maxSize() != cacheSize) {
|
||||||
Log.i(TAG, "Returned to full cache size");
|
Log.i(TAG, "Returned to full cache size");
|
||||||
cache.resize(cacheSize);
|
cache.resize(cacheSize);
|
||||||
}
|
}
|
||||||
@ -130,7 +127,7 @@ public class ImageLoader {
|
|||||||
private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) {
|
private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) {
|
||||||
String key;
|
String key;
|
||||||
int color;
|
int color;
|
||||||
if(entry == null) {
|
if (entry == null) {
|
||||||
key = getKey("unknown", size);
|
key = getKey("unknown", size);
|
||||||
color = COLORS[0];
|
color = COLORS[0];
|
||||||
|
|
||||||
@ -138,9 +135,9 @@ public class ImageLoader {
|
|||||||
} else {
|
} else {
|
||||||
key = getKey(entry.getId() + "unknown", size);
|
key = getKey(entry.getId() + "unknown", size);
|
||||||
String hash;
|
String hash;
|
||||||
if(entry.getAlbum() != null) {
|
if (entry.getAlbum() != null) {
|
||||||
hash = entry.getAlbum();
|
hash = entry.getAlbum();
|
||||||
} else if(entry.getArtist() != null) {
|
} else if (entry.getArtist() != null) {
|
||||||
hash = entry.getArtist();
|
hash = entry.getArtist();
|
||||||
} else {
|
} else {
|
||||||
hash = entry.getId();
|
hash = entry.getId();
|
||||||
@ -150,15 +147,17 @@ public class ImageLoader {
|
|||||||
return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist());
|
return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) {
|
private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) {
|
||||||
Bitmap bitmap = cache.get(key);
|
Bitmap bitmap = cache.get(key);
|
||||||
if(bitmap == null) {
|
if (bitmap == null) {
|
||||||
bitmap = createUnknownImage(size, color, topText, bottomText);
|
bitmap = createUnknownImage(size, color, topText, bottomText);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) {
|
private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) {
|
||||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
@ -170,17 +169,17 @@ public class ImageLoader {
|
|||||||
color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR));
|
color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR));
|
||||||
canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color);
|
canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color);
|
||||||
|
|
||||||
if(topText != null || bottomText != null) {
|
if (topText != null || bottomText != null) {
|
||||||
Paint font = new Paint();
|
Paint font = new Paint();
|
||||||
font.setFlags(Paint.ANTI_ALIAS_FLAG);
|
font.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||||
font.setColor(Color.WHITE);
|
font.setColor(Color.WHITE);
|
||||||
font.setTextSize(3.0f + size * 0.07f);
|
font.setTextSize(3.0f + size * 0.07f);
|
||||||
|
|
||||||
if(topText != null) {
|
if (topText != null) {
|
||||||
canvas.drawText(topText, size * 0.05f, size * 0.6f, font);
|
canvas.drawText(topText, size * 0.05f, size * 0.6f, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bottomText != null) {
|
if (bottomText != null) {
|
||||||
canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font);
|
canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,19 +189,19 @@ public class ImageLoader {
|
|||||||
|
|
||||||
public Bitmap getCachedImage(Context context, MusicDirectory.Entry entry, boolean large) {
|
public Bitmap getCachedImage(Context context, MusicDirectory.Entry entry, boolean large) {
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
if(entry == null || entry.getCoverArt() == null) {
|
if (entry == null || entry.getCoverArt() == null) {
|
||||||
return getUnknownImage(entry, size);
|
return getUnknownImage(entry, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
Bitmap bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
||||||
if(bitmap == null || bitmap.isRecycled()) {
|
if (bitmap == null || bitmap.isRecycled()) {
|
||||||
bitmap = FileUtil.getAlbumArtBitmap(context, entry, size);
|
bitmap = FileUtil.getAlbumArtBitmap(context, entry, size);
|
||||||
String key = getKey(entry.getCoverArt(), size);
|
String key = getKey(entry.getCoverArt(), size);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
cache.get(key);
|
cache.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bitmap != null && bitmap.isRecycled()) {
|
if (bitmap != null && bitmap.isRecycled()) {
|
||||||
bitmap = null;
|
bitmap = null;
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@ -212,16 +211,17 @@ public class ImageLoader {
|
|||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
return loadImage(view, entry, large, size, crossfade);
|
return loadImage(view, entry, large, size, crossfade);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
|
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
|
||||||
// If we know this a artist, try to load artist info instead
|
// If we know this a artist, try to load artist info instead
|
||||||
if(entry != null && !entry.isAlbum() && !Util.isOffline(context)) {
|
if (entry != null && !entry.isAlbum() && !Util.isOffline(context)) {
|
||||||
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, large, view, crossfade);
|
||||||
task.execute();
|
task.execute();
|
||||||
return task;
|
return task;
|
||||||
} else if(entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) {
|
} else if (entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) {
|
||||||
// Try to lookup child cover art
|
// Try to lookup child cover art
|
||||||
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, entry, true);
|
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, entry, true);
|
||||||
if(firstChild != null) {
|
if (firstChild != null) {
|
||||||
entry.setCoverArt(firstChild.getCoverArt());
|
entry.setCoverArt(firstChild.getCoverArt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ public class ImageLoader {
|
|||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
||||||
setImage(view, drawable, crossfade);
|
setImage(view, drawable, crossfade);
|
||||||
if(large) {
|
if (large) {
|
||||||
nowPlaying = bitmap;
|
nowPlaying = bitmap;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -246,39 +246,15 @@ public class ImageLoader {
|
|||||||
if (!large) {
|
if (!large) {
|
||||||
setImage(view, null, false);
|
setImage(view, null, false);
|
||||||
}
|
}
|
||||||
ImageTask task = new ViewImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
ImageTask task = new ViewImageTask(view.getContext(), entry, size, large, view, crossfade);
|
||||||
task.execute();
|
task.execute();
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SilentBackgroundTask<Void> loadImage(View view, String url, boolean large) {
|
public SilentBackgroundTask loadImage(View view, Playlist playlist) {
|
||||||
Bitmap bitmap;
|
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
|
||||||
if (url == null) {
|
|
||||||
String key = getKey(url + "unknown", size);
|
|
||||||
int color = COLORS[Math.abs(key.hashCode()) % COLORS.length];
|
|
||||||
bitmap = getUnknownImage(key, size, color, null, null);
|
|
||||||
setImage(view, Util.createDrawableFromBitmap(context, bitmap), true);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap = cache.get(getKey(url, size));
|
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
|
||||||
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
|
||||||
setImage(view, drawable, true);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
setImage(view, null, false);
|
|
||||||
|
|
||||||
SilentBackgroundTask<Void> task = new ViewUrlTask(view.getContext(), view, url, size);
|
|
||||||
task.execute();
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SilentBackgroundTask loadImage(View view, Playlist playlist, boolean large, boolean crossfade) {
|
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||||
String id;
|
String id;
|
||||||
if(Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
id = PLAYLIST_PREFIX + playlist.getName();
|
id = PLAYLIST_PREFIX + playlist.getName();
|
||||||
entry.setTitle(playlist.getComment());
|
entry.setTitle(playlist.getComment());
|
||||||
} else {
|
} else {
|
||||||
@ -290,7 +266,7 @@ public class ImageLoader {
|
|||||||
// So this isn't treated as a artist
|
// So this isn't treated as a artist
|
||||||
entry.setParent("");
|
entry.setParent("");
|
||||||
|
|
||||||
return loadImage(view, entry, large, crossfade);
|
return loadImage(view, entry, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey(String coverArtId, int size) {
|
private String getKey(String coverArtId, int size) {
|
||||||
@ -308,31 +284,28 @@ public class ImageLoader {
|
|||||||
Drawable existingDrawable = imageView.getDrawable();
|
Drawable existingDrawable = imageView.getDrawable();
|
||||||
if (existingDrawable == null) {
|
if (existingDrawable == null) {
|
||||||
Bitmap emptyImage;
|
Bitmap emptyImage;
|
||||||
if(drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
|
if (drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
|
||||||
emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
} else {
|
} else {
|
||||||
emptyImage = Bitmap.createBitmap(imageSizeDefault, imageSizeDefault, Bitmap.Config.ARGB_8888);
|
emptyImage = Bitmap.createBitmap(imageSizeDefault, imageSizeDefault, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
existingDrawable = new BitmapDrawable(context.getResources(), emptyImage);
|
existingDrawable = new BitmapDrawable(context.getResources(), emptyImage);
|
||||||
} else if(existingDrawable instanceof TransitionDrawable) {
|
} else if (existingDrawable instanceof TransitionDrawable) {
|
||||||
// This should only ever be used if user is skipping through many songs quickly
|
// This should only ever be used if user is skipping through many songs quickly
|
||||||
TransitionDrawable tmp = (TransitionDrawable) existingDrawable;
|
TransitionDrawable tmp = (TransitionDrawable) existingDrawable;
|
||||||
existingDrawable = tmp.getDrawable(tmp.getNumberOfLayers() - 1);
|
existingDrawable = tmp.getDrawable(tmp.getNumberOfLayers() - 1);
|
||||||
}
|
}
|
||||||
if(existingDrawable != null && drawable != null) {
|
if (existingDrawable != null && drawable != null) {
|
||||||
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
||||||
final TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
final TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
||||||
imageView.setImageDrawable(transitionDrawable);
|
imageView.setImageDrawable(transitionDrawable);
|
||||||
transitionDrawable.startTransition(250);
|
transitionDrawable.startTransition(250);
|
||||||
|
|
||||||
// Get rid of transition drawable after transition occurs
|
// Get rid of transition drawable after transition occurs
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(() -> {
|
||||||
@Override
|
// Only execute if still on same transition drawable
|
||||||
public void run() {
|
if (imageView.getDrawable() == transitionDrawable) {
|
||||||
// Only execute if still on same transition drawable
|
imageView.setImageDrawable(drawable);
|
||||||
if (imageView.getDrawable() == transitionDrawable) {
|
|
||||||
imageView.setImageDrawable(drawable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 500L);
|
}, 500L);
|
||||||
} else {
|
} else {
|
||||||
@ -345,19 +318,17 @@ public class ImageLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ImageTask extends SilentBackgroundTask<Void> {
|
public abstract class ImageTask extends SilentBackgroundTask<Void> {
|
||||||
|
final MusicDirectory.Entry mEntry;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
protected final MusicDirectory.Entry mEntry;
|
|
||||||
private final int mSize;
|
private final int mSize;
|
||||||
private final int mSaveSize;
|
|
||||||
private final boolean mIsNowPlaying;
|
private final boolean mIsNowPlaying;
|
||||||
protected Drawable mDrawable;
|
Drawable mDrawable;
|
||||||
|
|
||||||
public ImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying) {
|
public ImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
mSize = size;
|
mSize = size;
|
||||||
mSaveSize = saveSize;
|
|
||||||
mIsNowPlaying = isNowPlaying;
|
mIsNowPlaying = isNowPlaying;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +337,7 @@ public class ImageLoader {
|
|||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
||||||
Bitmap bitmap = musicService.getCoverArt(mContext, mEntry, mSize, null, this);
|
Bitmap bitmap = musicService.getCoverArt(mContext, mEntry, mSize, null, this);
|
||||||
if(bitmap != null) {
|
if (bitmap != null) {
|
||||||
String key = getKey(mEntry.getCoverArt(), mSize);
|
String key = getKey(mEntry.getCoverArt(), mSize);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
// Make sure key is the most recently "used"
|
// Make sure key is the most recently "used"
|
||||||
@ -389,11 +360,11 @@ public class ImageLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ViewImageTask extends ImageTask {
|
private class ViewImageTask extends ImageTask {
|
||||||
protected boolean mCrossfade;
|
final boolean mCrossfade;
|
||||||
private View mView;
|
private final View mView;
|
||||||
|
|
||||||
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade) {
|
||||||
super(context, entry, size, saveSize, isNowPlaying);
|
super(context, entry, size, isNowPlaying);
|
||||||
|
|
||||||
mView = view;
|
mView = view;
|
||||||
mCrossfade = crossfade;
|
mCrossfade = crossfade;
|
||||||
@ -409,20 +380,17 @@ public class ImageLoader {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final MusicDirectory.Entry mEntry;
|
private final MusicDirectory.Entry mEntry;
|
||||||
private final int mSize;
|
private final int mSize;
|
||||||
private final int mSaveSize;
|
|
||||||
private final boolean mIsNowPlaying;
|
private final boolean mIsNowPlaying;
|
||||||
|
private final boolean mCrossfade;
|
||||||
|
private final View mView;
|
||||||
private Drawable mDrawable;
|
private Drawable mDrawable;
|
||||||
private boolean mCrossfade;
|
|
||||||
private View mView;
|
|
||||||
|
|
||||||
private SilentBackgroundTask subTask;
|
private SilentBackgroundTask subTask;
|
||||||
|
|
||||||
public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
mSize = size;
|
mSize = size;
|
||||||
mSaveSize = saveSize;
|
|
||||||
mIsNowPlaying = isNowPlaying;
|
mIsNowPlaying = isNowPlaying;
|
||||||
mView = view;
|
mView = view;
|
||||||
mCrossfade = crossfade;
|
mCrossfade = crossfade;
|
||||||
@ -431,8 +399,6 @@ public class ImageLoader {
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
|
||||||
|
|
||||||
// Figure out whether we are going to get a artist image or the standard image
|
// Figure out whether we are going to get a artist image or the standard image
|
||||||
if (mEntry != null && mEntry.getCoverArt() == null && mEntry.isDirectory() && !Util.isOffline(context)) {
|
if (mEntry != null && mEntry.getCoverArt() == null && mEntry.isDirectory() && !Util.isOffline(context)) {
|
||||||
// Try to lookup child cover art
|
// Try to lookup child cover art
|
||||||
@ -443,7 +409,7 @@ public class ImageLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mEntry != null && mEntry.getCoverArt() != null) {
|
if (mEntry != null && mEntry.getCoverArt() != null) {
|
||||||
subTask = new ViewImageTask(mContext, mEntry, mSize, mSaveSize, mIsNowPlaying, mView, mCrossfade);
|
subTask = new ViewImageTask(mContext, mEntry, mSize, mIsNowPlaying, mView, mCrossfade);
|
||||||
} else {
|
} else {
|
||||||
// If entry is null as well, we need to just set as a blank image
|
// If entry is null as well, we need to just set as a blank image
|
||||||
Bitmap bitmap = getUnknownImage(mEntry, mSize);
|
Bitmap bitmap = getUnknownImage(mEntry, mSize);
|
||||||
@ -462,61 +428,11 @@ public class ImageLoader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(Void result) {
|
public void done(Void result) {
|
||||||
if(subTask != null) {
|
if (subTask != null) {
|
||||||
subTask.done(result);
|
subTask.done(result);
|
||||||
} else if(mDrawable != null) {
|
} else if (mDrawable != null) {
|
||||||
setImage(mView, mDrawable, mCrossfade);
|
setImage(mView, mDrawable, mCrossfade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ViewUrlTask extends SilentBackgroundTask<Void> {
|
|
||||||
private final Context mContext;
|
|
||||||
private final String mUrl;
|
|
||||||
private final ImageView mView;
|
|
||||||
private Drawable mDrawable;
|
|
||||||
private int mSize;
|
|
||||||
|
|
||||||
public ViewUrlTask(Context context, View view, String url, int size) {
|
|
||||||
super(context);
|
|
||||||
mContext = context;
|
|
||||||
mView = (ImageView) view;
|
|
||||||
mUrl = url;
|
|
||||||
mSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground() throws Throwable {
|
|
||||||
try {
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
|
||||||
Bitmap bitmap = musicService.getBitmap(mUrl, mSize, mContext, null, this);
|
|
||||||
if(bitmap != null) {
|
|
||||||
String key = getKey(mUrl, mSize);
|
|
||||||
cache.put(key, bitmap);
|
|
||||||
// Make sure key is the most recently "used"
|
|
||||||
cache.get(key);
|
|
||||||
|
|
||||||
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
|
|
||||||
}
|
|
||||||
} catch (Throwable x) {
|
|
||||||
Log.e(TAG, "Failed to download from url " + mUrl, x);
|
|
||||||
cancelled.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done(Void result) {
|
|
||||||
if(mDrawable != null) {
|
|
||||||
mView.setImageDrawable(mDrawable);
|
|
||||||
} else {
|
|
||||||
failedToDownload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void failedToDownload() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package net.nullsum.audinaut.util;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.activity.SubsonicActivity;
|
import net.nullsum.audinaut.activity.SubsonicActivity;
|
||||||
|
|
||||||
@ -13,14 +12,15 @@ import net.nullsum.audinaut.activity.SubsonicActivity;
|
|||||||
public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
||||||
|
|
||||||
private final Activity tabActivity;
|
private final Activity tabActivity;
|
||||||
private ProgressDialog loading;
|
|
||||||
private final boolean cancellable;
|
private final boolean cancellable;
|
||||||
|
private ProgressDialog loading;
|
||||||
|
|
||||||
public LoadingTask(Activity activity) {
|
public LoadingTask(Activity activity) {
|
||||||
super(activity);
|
super(activity);
|
||||||
tabActivity = activity;
|
tabActivity = activity;
|
||||||
this.cancellable = true;
|
this.cancellable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadingTask(Activity activity, final boolean cancellable) {
|
public LoadingTask(Activity activity, final boolean cancellable) {
|
||||||
super(activity);
|
super(activity);
|
||||||
tabActivity = activity;
|
tabActivity = activity;
|
||||||
@ -29,16 +29,12 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() {
|
loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, dialog -> cancel());
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
queue.offer(task = new Task() {
|
queue.offer(task = new Task() {
|
||||||
@Override
|
@Override
|
||||||
public void onDone(T result) {
|
public void onDone(T result) {
|
||||||
if(loading.isShowing()) {
|
if (loading.isShowing()) {
|
||||||
loading.dismiss();
|
loading.dismiss();
|
||||||
}
|
}
|
||||||
done(result);
|
done(result);
|
||||||
@ -46,7 +42,7 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
if(loading.isShowing()) {
|
if (loading.isShowing()) {
|
||||||
loading.dismiss();
|
loading.dismiss();
|
||||||
}
|
}
|
||||||
error(t);
|
error(t);
|
||||||
@ -61,13 +57,8 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(final String message) {
|
public void updateProgress(final String message) {
|
||||||
if(!cancelled.get()) {
|
if (!cancelled.get()) {
|
||||||
getHandler().post(new Runnable() {
|
getHandler().post(() -> loading.setMessage(message));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
loading.setMessage(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,9 @@
|
|||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
import net.nullsum.audinaut.view.AlbumView;
|
import net.nullsum.audinaut.view.AlbumView;
|
||||||
@ -30,21 +27,23 @@ import net.nullsum.audinaut.view.ArtistView;
|
|||||||
import net.nullsum.audinaut.view.SongView;
|
import net.nullsum.audinaut.view.SongView;
|
||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public final class MenuUtil {
|
public final class MenuUtil {
|
||||||
private final static String TAG = MenuUtil.class.getSimpleName();
|
private final static String TAG = MenuUtil.class.getSimpleName();
|
||||||
|
|
||||||
public static void hideMenuItems(Context context, Menu menu, UpdateView updateView) {
|
public static void hideMenuItems(Context context, Menu menu, UpdateView updateView) {
|
||||||
if(!Util.isOffline(context)) {
|
if (!Util.isOffline(context)) {
|
||||||
// If we are looking at a standard song view, get downloadFile to cache what options to show
|
// If we are looking at a standard song view, get downloadFile to cache what options to show
|
||||||
if(updateView instanceof SongView) {
|
if (updateView instanceof SongView) {
|
||||||
SongView songView = (SongView) updateView;
|
SongView songView = (SongView) updateView;
|
||||||
DownloadFile downloadFile = songView.getDownloadFile();
|
DownloadFile downloadFile = songView.getDownloadFile();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(downloadFile != null) {
|
if (downloadFile != null) {
|
||||||
if(downloadFile.isWorkDone()) {
|
if (downloadFile.isWorkDone()) {
|
||||||
// Remove permanent cache menu if already perma cached
|
// Remove permanent cache menu if already perma cached
|
||||||
if(downloadFile.isSaved()) {
|
if (downloadFile.isSaved()) {
|
||||||
menu.setGroupVisible(R.id.hide_pin, false);
|
menu.setGroupVisible(R.id.hide_pin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,26 +54,26 @@ public final class MenuUtil {
|
|||||||
menu.setGroupVisible(R.id.hide_delete, false);
|
menu.setGroupVisible(R.id.hide_delete, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to lookup downloadFile info", e);
|
Log.w(TAG, "Failed to lookup downloadFile info", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Apply similar logic to album views
|
// Apply similar logic to album views
|
||||||
else if(updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) {
|
else if (updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) {
|
||||||
File folder = null;
|
File folder = null;
|
||||||
if(updateView instanceof AlbumView) {
|
if (updateView instanceof AlbumView) {
|
||||||
folder = ((AlbumView) updateView).getFile();
|
folder = ((AlbumView) updateView).getFile();
|
||||||
} else if(updateView instanceof ArtistView) {
|
} else if (updateView instanceof ArtistView) {
|
||||||
folder = ((ArtistView) updateView).getFile();
|
folder = ((ArtistView) updateView).getFile();
|
||||||
} else if(updateView instanceof ArtistEntryView) {
|
} else if (updateView instanceof ArtistEntryView) {
|
||||||
folder = ((ArtistEntryView) updateView).getFile();
|
folder = ((ArtistEntryView) updateView).getFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(folder != null && !folder.exists()) {
|
if (folder != null && !folder.exists()) {
|
||||||
menu.setGroupVisible(R.id.hide_delete, false);
|
menu.setGroupVisible(R.id.hide_delete, false);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to lookup album directory info", e);
|
Log.w(TAG, "Failed to lookup album directory info", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,14 +43,11 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
import static android.content.Context.NOTIFICATION_SERVICE;
|
||||||
|
|
||||||
public final class Notifications {
|
public final class Notifications {
|
||||||
|
private static final int NOTIFICATION_ID_PLAYING = 100;
|
||||||
|
private static final int NOTIFICATION_ID_DOWNLOADING = 102;
|
||||||
|
private static final String CHANNEL_PLAYING_ID = "playback_controls";
|
||||||
|
private static final String CHANNEL_DOWNLOADING_ID = "media_download";
|
||||||
private static final String TAG = Notifications.class.getSimpleName();
|
private static final String TAG = Notifications.class.getSimpleName();
|
||||||
|
|
||||||
public static final int NOTIFICATION_ID_PLAYING = 100;
|
|
||||||
public static final int NOTIFICATION_ID_DOWNLOADING = 102;
|
|
||||||
|
|
||||||
public static final String CHANNEL_PLAYING_ID = "playback_controls";
|
|
||||||
public static final String CHANNEL_DOWNLOADING_ID = "media_download";
|
|
||||||
|
|
||||||
private static boolean playShowing = false;
|
private static boolean playShowing = false;
|
||||||
private static boolean downloadShowing = false;
|
private static boolean downloadShowing = false;
|
||||||
private static boolean downloadForeground = false;
|
private static boolean downloadForeground = false;
|
||||||
@ -71,7 +68,7 @@ public final class Notifications {
|
|||||||
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
|
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
|
||||||
|
|
||||||
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
|
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
|
||||||
setupViews(expandedContentView ,context, song, true, playing);
|
setupViews(expandedContentView, context, song, true, playing);
|
||||||
|
|
||||||
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
|
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
|
||||||
setupViews(smallContentView, context, song, false, playing);
|
setupViews(smallContentView, context, song, false, playing);
|
||||||
@ -93,29 +90,23 @@ public final class Notifications {
|
|||||||
.setPriority(NotificationCompat.PRIORITY_LOW).build();
|
.setPriority(NotificationCompat.PRIORITY_LOW).build();
|
||||||
|
|
||||||
playShowing = true;
|
playShowing = true;
|
||||||
if(downloadForeground && downloadShowing) {
|
if (downloadForeground && downloadShowing) {
|
||||||
downloadForeground = false;
|
downloadForeground = false;
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> {
|
||||||
@Override
|
downloadService.stopForeground(true);
|
||||||
public void run() {
|
showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size());
|
||||||
downloadService.stopForeground(true);
|
downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification);
|
||||||
showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size());
|
|
||||||
downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> {
|
||||||
@Override
|
if (playing) {
|
||||||
public void run() {
|
downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification);
|
||||||
if (playing) {
|
} else {
|
||||||
downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification);
|
playShowing = false;
|
||||||
} else {
|
persistentPlayingShowing = true;
|
||||||
playShowing = false;
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
persistentPlayingShowing = true;
|
downloadService.stopForeground(false);
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
notificationManager.notify(NOTIFICATION_ID_PLAYING, notification);
|
||||||
downloadService.stopForeground(false);
|
|
||||||
notificationManager.notify(NOTIFICATION_ID_PLAYING, notification);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,7 +125,7 @@ public final class Notifications {
|
|||||||
try {
|
try {
|
||||||
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
||||||
Bitmap bitmap = null;
|
Bitmap bitmap = null;
|
||||||
if(imageLoader != null) {
|
if (imageLoader != null) {
|
||||||
bitmap = imageLoader.getCachedImage(context, song, false);
|
bitmap = imageLoader.getCachedImage(context, song, false);
|
||||||
}
|
}
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
@ -155,8 +146,8 @@ public final class Notifications {
|
|||||||
rv.setTextViewText(R.id.notification_album, album);
|
rv.setTextViewText(R.id.notification_album, album);
|
||||||
|
|
||||||
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
|
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
|
||||||
if(persistent) {
|
if (persistent) {
|
||||||
if(expanded) {
|
if (expanded) {
|
||||||
rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_pause : R.drawable.notification_start);
|
rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_pause : R.drawable.notification_start);
|
||||||
|
|
||||||
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_backward);
|
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_backward);
|
||||||
@ -174,8 +165,8 @@ public final class Notifications {
|
|||||||
|
|
||||||
// Create actions for media buttons
|
// Create actions for media buttons
|
||||||
PendingIntent pendingIntent;
|
PendingIntent pendingIntent;
|
||||||
int previous = 0, pause = 0, next = 0, close = 0, rewind = 0, fastForward = 0;
|
int previous = 0, pause, next, close = 0, rewind = 0, fastForward = 0;
|
||||||
if(persistent && !expanded) {
|
if (persistent && !expanded) {
|
||||||
pause = R.id.control_previous;
|
pause = R.id.control_previous;
|
||||||
next = R.id.control_pause;
|
next = R.id.control_pause;
|
||||||
close = R.id.control_next;
|
close = R.id.control_next;
|
||||||
@ -185,27 +176,27 @@ public final class Notifications {
|
|||||||
next = R.id.control_next;
|
next = R.id.control_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(persistent && close == 0 && expanded) {
|
if (persistent && close == 0 && expanded) {
|
||||||
close = R.id.notification_close;
|
close = R.id.notification_close;
|
||||||
rv.setViewVisibility(close, View.VISIBLE);
|
rv.setViewVisibility(close, View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(previous > 0) {
|
if (previous > 0) {
|
||||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
|
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
|
||||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
||||||
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
||||||
rv.setOnClickPendingIntent(previous, pendingIntent);
|
rv.setOnClickPendingIntent(previous, pendingIntent);
|
||||||
}
|
}
|
||||||
if(rewind > 0) {
|
if (rewind > 0) {
|
||||||
Intent rewindIntent = new Intent("KEYCODE_MEDIA_REWIND");
|
Intent rewindIntent = new Intent("KEYCODE_MEDIA_REWIND");
|
||||||
rewindIntent.setComponent(new ComponentName(context, DownloadService.class));
|
rewindIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
rewindIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND));
|
rewindIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND));
|
||||||
pendingIntent = PendingIntent.getService(context, 0, rewindIntent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, rewindIntent, 0);
|
||||||
rv.setOnClickPendingIntent(rewind, pendingIntent);
|
rv.setOnClickPendingIntent(rewind, pendingIntent);
|
||||||
}
|
}
|
||||||
if(pause > 0) {
|
if (pause > 0) {
|
||||||
if(playing) {
|
if (playing) {
|
||||||
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
|
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
|
||||||
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
|
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
|
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
|
||||||
@ -219,21 +210,21 @@ public final class Notifications {
|
|||||||
rv.setOnClickPendingIntent(pause, pendingIntent);
|
rv.setOnClickPendingIntent(pause, pendingIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(next > 0) {
|
if (next > 0) {
|
||||||
Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
|
Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
|
||||||
nextIntent.setComponent(new ComponentName(context, DownloadService.class));
|
nextIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
|
nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
|
||||||
pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
|
||||||
rv.setOnClickPendingIntent(next, pendingIntent);
|
rv.setOnClickPendingIntent(next, pendingIntent);
|
||||||
}
|
}
|
||||||
if(fastForward > 0) {
|
if (fastForward > 0) {
|
||||||
Intent fastForwardIntent = new Intent("KEYCODE_MEDIA_FAST_FORWARD");
|
Intent fastForwardIntent = new Intent("KEYCODE_MEDIA_FAST_FORWARD");
|
||||||
fastForwardIntent.setComponent(new ComponentName(context, DownloadService.class));
|
fastForwardIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
fastForwardIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
|
fastForwardIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
|
||||||
pendingIntent = PendingIntent.getService(context, 0, fastForwardIntent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, fastForwardIntent, 0);
|
||||||
rv.setOnClickPendingIntent(fastForward, pendingIntent);
|
rv.setOnClickPendingIntent(fastForward, pendingIntent);
|
||||||
}
|
}
|
||||||
if(close > 0) {
|
if (close > 0) {
|
||||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
|
Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
|
||||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
|
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
|
||||||
@ -246,21 +237,18 @@ public final class Notifications {
|
|||||||
playShowing = false;
|
playShowing = false;
|
||||||
|
|
||||||
// Remove notification and remove the service from the foreground
|
// Remove notification and remove the service from the foreground
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> {
|
||||||
@Override
|
downloadService.stopForeground(true);
|
||||||
public void run() {
|
|
||||||
downloadService.stopForeground(true);
|
|
||||||
|
|
||||||
if(persistentPlayingShowing) {
|
if (persistentPlayingShowing) {
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
notificationManager.cancel(NOTIFICATION_ID_PLAYING);
|
notificationManager.cancel(NOTIFICATION_ID_PLAYING);
|
||||||
persistentPlayingShowing = false;
|
persistentPlayingShowing = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get downloadNotification in foreground if playing
|
// Get downloadNotification in foreground if playing
|
||||||
if(downloadShowing) {
|
if (downloadShowing) {
|
||||||
showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size());
|
showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +262,7 @@ public final class Notifications {
|
|||||||
PendingIntent cancelPI = PendingIntent.getService(context, 0, cancelIntent, 0);
|
PendingIntent cancelPI = PendingIntent.getService(context, 0, cancelIntent, 0);
|
||||||
|
|
||||||
String currentDownloading, currentSize;
|
String currentDownloading, currentSize;
|
||||||
if(file != null) {
|
if (file != null) {
|
||||||
currentDownloading = file.getSong().getTitle();
|
currentDownloading = file.getSong().getTitle();
|
||||||
currentSize = Util.formatLocalizedBytes(file.getEstimatedSize(), context);
|
currentSize = Util.formatLocalizedBytes(file.getEstimatedSize(), context);
|
||||||
} else {
|
} else {
|
||||||
@ -307,37 +295,28 @@ public final class Notifications {
|
|||||||
cancelPI)
|
cancelPI)
|
||||||
.setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0))
|
.setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0))
|
||||||
.setStyle(new NotificationCompat.BigTextStyle()
|
.setStyle(new NotificationCompat.BigTextStyle()
|
||||||
.bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize)))
|
.bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize)))
|
||||||
.setProgress(10, 5, true).build();
|
.setProgress(10, 5, true).build();
|
||||||
|
|
||||||
downloadShowing = true;
|
downloadShowing = true;
|
||||||
if(playShowing) {
|
if (playShowing) {
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
notificationManager.notify(NOTIFICATION_ID_DOWNLOADING, notification);
|
notificationManager.notify(NOTIFICATION_ID_DOWNLOADING, notification);
|
||||||
} else {
|
} else {
|
||||||
downloadForeground = true;
|
downloadForeground = true;
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> downloadService.startForeground(NOTIFICATION_ID_DOWNLOADING, notification));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
downloadService.startForeground(NOTIFICATION_ID_DOWNLOADING, notification);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hideDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler) {
|
public static void hideDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler) {
|
||||||
downloadShowing = false;
|
downloadShowing = false;
|
||||||
if(playShowing) {
|
if (playShowing) {
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING);
|
notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING);
|
||||||
} else {
|
} else {
|
||||||
downloadForeground = false;
|
downloadForeground = false;
|
||||||
handler.post(new Runnable() {
|
handler.post(() -> downloadService.stopForeground(true));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
downloadService.stopForeground(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,8 @@ import java.io.Serializable;
|
|||||||
*/
|
*/
|
||||||
public class Pair<S, T> implements Serializable {
|
public class Pair<S, T> implements Serializable {
|
||||||
|
|
||||||
private S first;
|
private final S first;
|
||||||
private T second;
|
private final T second;
|
||||||
|
|
||||||
public Pair() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pair(S first, T second) {
|
public Pair(S first, T second) {
|
||||||
this.first = first;
|
this.first = first;
|
||||||
@ -40,15 +37,8 @@ public class Pair<S, T> implements Serializable {
|
|||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFirst(S first) {
|
|
||||||
this.first = first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getSecond() {
|
public T getSecond() {
|
||||||
return second;
|
return second;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecond(T second) {
|
|
||||||
this.second = second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user