2023-03-06 14:42:04 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
// Copyright The Music Player Daemon Project
|
2014-09-16 12:00:59 +02:00
|
|
|
|
|
|
|
package org.musicpd;
|
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
import java.util.LinkedList;
|
|
|
|
|
2019-05-04 07:29:41 +02:00
|
|
|
import android.Manifest;
|
2014-09-16 12:00:59 +02:00
|
|
|
import android.app.Activity;
|
2014-10-18 19:02:23 +02:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.content.SharedPreferences.Editor;
|
2019-05-04 07:29:41 +02:00
|
|
|
import android.content.pm.PackageManager;
|
2014-09-16 12:00:59 +02:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Handler;
|
|
|
|
import android.os.Message;
|
|
|
|
import android.util.Log;
|
2014-10-18 19:02:23 +02:00
|
|
|
import android.widget.ArrayAdapter;
|
|
|
|
import android.widget.CheckBox;
|
2014-09-16 12:00:59 +02:00
|
|
|
import android.widget.CompoundButton;
|
|
|
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
2014-10-18 19:02:23 +02:00
|
|
|
import android.widget.ListView;
|
2014-09-16 12:00:59 +02:00
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.ToggleButton;
|
|
|
|
|
|
|
|
public class Settings extends Activity {
|
|
|
|
private static final String TAG = "Settings";
|
|
|
|
private Main.Client mClient;
|
2014-10-18 19:02:23 +02:00
|
|
|
private TextView mTextStatus;
|
|
|
|
private ToggleButton mRunButton;
|
|
|
|
private boolean mFirstRun;
|
|
|
|
private LinkedList<String> mLogListArray = new LinkedList<String>();
|
|
|
|
private ListView mLogListView;
|
|
|
|
private ArrayAdapter<String> mLogListAdapter;
|
|
|
|
|
|
|
|
private static final int MAX_LOGS = 500;
|
2014-09-16 12:00:59 +02:00
|
|
|
|
|
|
|
private static final int MSG_ERROR = 0;
|
|
|
|
private static final int MSG_STOPPED = 1;
|
|
|
|
private static final int MSG_STARTED = 2;
|
2014-10-18 19:02:23 +02:00
|
|
|
private static final int MSG_LOG = 3;
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
public static class Preferences {
|
|
|
|
public static final String KEY_RUN_ON_BOOT ="run_on_boot";
|
|
|
|
public static final String KEY_WAKELOCK ="wakelock";
|
2021-07-26 19:55:39 +02:00
|
|
|
public static final String KEY_PAUSE_ON_HEADPHONES_DISCONNECT ="pause_on_headphones_disconnect";
|
2014-10-18 19:02:23 +02:00
|
|
|
|
|
|
|
public static SharedPreferences get(Context context) {
|
|
|
|
return context.getSharedPreferences(TAG, MODE_PRIVATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void putBoolean(Context context, String key, boolean value) {
|
|
|
|
final SharedPreferences prefs = get(context);
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
if (prefs == null)
|
|
|
|
return;
|
|
|
|
final Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(key, value);
|
|
|
|
editor.apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean getBoolean(Context context, String key, boolean defValue) {
|
|
|
|
final SharedPreferences prefs = get(context);
|
|
|
|
|
|
|
|
return prefs != null ? prefs.getBoolean(key, defValue) : defValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private Handler mHandler = new Handler(new Handler.Callback() {
|
2014-09-16 12:00:59 +02:00
|
|
|
@Override
|
|
|
|
public boolean handleMessage(Message msg) {
|
|
|
|
switch (msg.what) {
|
|
|
|
case MSG_ERROR:
|
|
|
|
Log.d(TAG, "onError");
|
2014-10-18 19:02:23 +02:00
|
|
|
|
|
|
|
mClient.release();
|
|
|
|
connectClient();
|
|
|
|
|
|
|
|
mRunButton.setEnabled(false);
|
|
|
|
mRunButton.setChecked(false);
|
|
|
|
|
|
|
|
mTextStatus.setText((String)msg.obj);
|
|
|
|
mFirstRun = true;
|
2014-09-16 12:00:59 +02:00
|
|
|
break;
|
|
|
|
case MSG_STOPPED:
|
|
|
|
Log.d(TAG, "onStopped");
|
2014-10-18 19:02:23 +02:00
|
|
|
mRunButton.setEnabled(true);
|
|
|
|
if (!mFirstRun && Preferences.getBoolean(Settings.this, Preferences.KEY_RUN_ON_BOOT, false))
|
|
|
|
mRunButton.setChecked(true);
|
|
|
|
else
|
|
|
|
mRunButton.setChecked(false);
|
|
|
|
mFirstRun = true;
|
2020-03-25 22:23:10 +01:00
|
|
|
mTextStatus.setText("");
|
2014-09-16 12:00:59 +02:00
|
|
|
break;
|
|
|
|
case MSG_STARTED:
|
|
|
|
Log.d(TAG, "onStarted");
|
2014-10-18 19:02:23 +02:00
|
|
|
mRunButton.setChecked(true);
|
|
|
|
mFirstRun = true;
|
2020-03-25 22:23:10 +01:00
|
|
|
mTextStatus.setText("MPD service started");
|
2014-10-18 19:02:23 +02:00
|
|
|
break;
|
|
|
|
case MSG_LOG:
|
|
|
|
if (mLogListArray.size() > MAX_LOGS)
|
|
|
|
mLogListArray.remove(0);
|
|
|
|
String priority;
|
|
|
|
switch (msg.arg1) {
|
|
|
|
case Log.DEBUG:
|
|
|
|
priority = "D";
|
|
|
|
break;
|
|
|
|
case Log.ERROR:
|
|
|
|
priority = "E";
|
|
|
|
break;
|
|
|
|
case Log.INFO:
|
|
|
|
priority = "I";
|
|
|
|
break;
|
|
|
|
case Log.VERBOSE:
|
|
|
|
priority = "V";
|
|
|
|
break;
|
|
|
|
case Log.WARN:
|
|
|
|
priority = "W";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
priority = "";
|
|
|
|
}
|
|
|
|
mLogListArray.add(priority + "/ " + (String)msg.obj);
|
|
|
|
mLogListAdapter.notifyDataSetChanged();
|
|
|
|
|
2014-09-16 12:00:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
private final OnCheckedChangeListener mOnRunChangeListener = new OnCheckedChangeListener() {
|
2014-09-16 12:00:59 +02:00
|
|
|
@Override
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
if (mClient != null) {
|
2014-10-18 19:02:23 +02:00
|
|
|
if (isChecked) {
|
2014-09-16 12:00:59 +02:00
|
|
|
mClient.start();
|
2014-10-18 19:02:23 +02:00
|
|
|
if (Preferences.getBoolean(Settings.this,
|
|
|
|
Preferences.KEY_WAKELOCK, false))
|
|
|
|
mClient.setWakelockEnabled(true);
|
2021-07-26 19:55:39 +02:00
|
|
|
if (Preferences.getBoolean(Settings.this,
|
|
|
|
Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false))
|
|
|
|
mClient.setPauseOnHeadphonesDisconnect(true);
|
2014-10-18 19:02:23 +02:00
|
|
|
} else {
|
2014-09-16 12:00:59 +02:00
|
|
|
mClient.stop();
|
2014-10-18 19:02:23 +02:00
|
|
|
}
|
2014-09-16 12:00:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
private final OnCheckedChangeListener mOnRunOnBootChangeListener = new OnCheckedChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
Preferences.putBoolean(Settings.this, Preferences.KEY_RUN_ON_BOOT, isChecked);
|
|
|
|
if (isChecked && mClient != null && !mRunButton.isChecked())
|
|
|
|
mRunButton.setChecked(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private final OnCheckedChangeListener mOnWakelockChangeListener = new OnCheckedChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
Preferences.putBoolean(Settings.this, Preferences.KEY_WAKELOCK, isChecked);
|
|
|
|
if (mClient != null && mClient.isRunning())
|
|
|
|
mClient.setWakelockEnabled(isChecked);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-07-26 19:55:39 +02:00
|
|
|
private final OnCheckedChangeListener mOnPauseOnHeadphonesDisconnectChangeListener = new OnCheckedChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
Preferences.putBoolean(Settings.this, Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, isChecked);
|
|
|
|
if (mClient != null && mClient.isRunning())
|
|
|
|
mClient.setPauseOnHeadphonesDisconnect(isChecked);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-16 12:00:59 +02:00
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
2019-05-04 07:29:41 +02:00
|
|
|
/* TODO: this sure is the wrong place to request
|
|
|
|
permissions - it will cause MPD to quit
|
|
|
|
immediately; we should request permissions when we
|
|
|
|
need them, but implementing that is complicated, so
|
|
|
|
for now, we do it here to give users a quick
|
|
|
|
solution for the problem */
|
|
|
|
requestAllPermissions();
|
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
setContentView(R.layout.settings);
|
|
|
|
mRunButton = (ToggleButton) findViewById(R.id.run);
|
|
|
|
mRunButton.setOnCheckedChangeListener(mOnRunChangeListener);
|
|
|
|
|
|
|
|
mTextStatus = (TextView) findViewById(R.id.status);
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
mLogListAdapter = new ArrayAdapter<String>(this, R.layout.log_item, mLogListArray);
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
mLogListView = (ListView) findViewById(R.id.log_list);
|
|
|
|
mLogListView.setAdapter(mLogListAdapter);
|
|
|
|
mLogListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
CheckBox checkbox = (CheckBox) findViewById(R.id.run_on_boot);
|
|
|
|
checkbox.setOnCheckedChangeListener(mOnRunOnBootChangeListener);
|
|
|
|
if (Preferences.getBoolean(this, Preferences.KEY_RUN_ON_BOOT, false))
|
|
|
|
checkbox.setChecked(true);
|
|
|
|
|
|
|
|
checkbox = (CheckBox) findViewById(R.id.wakelock);
|
|
|
|
checkbox.setOnCheckedChangeListener(mOnWakelockChangeListener);
|
|
|
|
if (Preferences.getBoolean(this, Preferences.KEY_WAKELOCK, false))
|
|
|
|
checkbox.setChecked(true);
|
2014-09-16 12:00:59 +02:00
|
|
|
|
2021-07-26 19:55:39 +02:00
|
|
|
checkbox = (CheckBox) findViewById(R.id.pause_on_headphones_disconnect);
|
|
|
|
checkbox.setOnCheckedChangeListener(mOnPauseOnHeadphonesDisconnectChangeListener);
|
|
|
|
if (Preferences.getBoolean(this, Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false))
|
|
|
|
checkbox.setChecked(true);
|
|
|
|
|
2014-09-16 12:00:59 +02:00
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
}
|
|
|
|
|
2019-05-04 07:29:41 +02:00
|
|
|
private void checkRequestPermission(String permission) {
|
|
|
|
if (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
try {
|
|
|
|
this.requestPermissions(new String[]{permission}, 0);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(TAG, "requestPermissions(" + permission + ") failed",
|
|
|
|
e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void requestAllPermissions() {
|
|
|
|
if (android.os.Build.VERSION.SDK_INT < 23)
|
|
|
|
/* we don't need to request permissions on
|
|
|
|
this old Android version */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* starting with Android 6.0, we need to explicitly
|
|
|
|
request all permissions before using them;
|
|
|
|
mentioning them in the manifest is not enough */
|
|
|
|
|
|
|
|
checkRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
|
|
|
|
}
|
|
|
|
|
2014-10-18 19:02:23 +02:00
|
|
|
private void connectClient() {
|
2014-09-16 12:00:59 +02:00
|
|
|
mClient = new Main.Client(this, new Main.Client.Callback() {
|
2014-10-18 19:02:23 +02:00
|
|
|
|
|
|
|
private void removeMessages() {
|
|
|
|
/* don't remove log messages */
|
|
|
|
mHandler.removeMessages(MSG_STOPPED);
|
|
|
|
mHandler.removeMessages(MSG_STARTED);
|
|
|
|
mHandler.removeMessages(MSG_ERROR);
|
|
|
|
}
|
|
|
|
|
2014-09-16 12:00:59 +02:00
|
|
|
@Override
|
|
|
|
public void onStopped() {
|
2014-10-18 19:02:23 +02:00
|
|
|
removeMessages();
|
2014-09-16 12:00:59 +02:00
|
|
|
mHandler.sendEmptyMessage(MSG_STOPPED);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStarted() {
|
2014-10-18 19:02:23 +02:00
|
|
|
removeMessages();
|
2014-09-16 12:00:59 +02:00
|
|
|
mHandler.sendEmptyMessage(MSG_STARTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onError(String error) {
|
2014-10-18 19:02:23 +02:00
|
|
|
removeMessages();
|
2014-09-16 12:00:59 +02:00
|
|
|
mHandler.sendMessage(Message.obtain(mHandler, MSG_ERROR, error));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLog(int priority, String msg) {
|
2014-10-18 19:02:23 +02:00
|
|
|
mHandler.sendMessage(Message.obtain(mHandler, MSG_LOG, priority, 0, msg));
|
2014-09-16 12:00:59 +02:00
|
|
|
}
|
|
|
|
});
|
2014-10-18 19:02:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onStart() {
|
|
|
|
mFirstRun = false;
|
|
|
|
connectClient();
|
2014-09-16 12:00:59 +02:00
|
|
|
super.onStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onStop() {
|
|
|
|
mClient.release();
|
|
|
|
mClient = null;
|
|
|
|
super.onStop();
|
|
|
|
}
|
|
|
|
}
|