Skip to content

Commit

Permalink
Android: add option to pause MPD when headphones disconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
sambazley committed Jul 26, 2021
1 parent d39b11b commit 5768777
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 0 deletions.
3 changes: 3 additions & 0 deletions android/AndroidManifest.xml
Expand Up @@ -17,6 +17,8 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />

<application android:allowBackup="true"
android:requestLegacyExternalStorage="true"
Expand All @@ -41,6 +43,7 @@
<receiver android:name=".Receiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
<service android:name=".Main" android:process=":main"/>
Expand Down
6 changes: 6 additions & 0 deletions android/res/layout/settings.xml
Expand Up @@ -23,6 +23,12 @@
android:layout_height="wrap_content"
android:text="@string/checkbox_wakelock" />

<CheckBox
android:id="@+id/pause_on_headphones_disconnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/checkbox_pause_on_headphones_disconnect" />

<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
Expand Down
1 change: 1 addition & 0 deletions android/res/values/strings.xml
Expand Up @@ -8,4 +8,5 @@
<string name="toggle_button_run_off">MPD is not running</string>
<string name="checkbox_run_on_boot">Run MPD automatically on boot</string>
<string name="checkbox_wakelock">Prevent suspend when MPD is running (Wakelock)</string>
<string name="checkbox_pause_on_headphones_disconnect">Pause MPD when headphones disconnect</string>
</resources>
1 change: 1 addition & 0 deletions android/src/Bridge.java
Expand Up @@ -33,4 +33,5 @@ public interface LogListener {

public static native void run(Context context, LogListener logListener);
public static native void shutdown();
public static native void pause();
}
1 change: 1 addition & 0 deletions android/src/IMain.aidl
Expand Up @@ -5,6 +5,7 @@ interface IMain
{
void start();
void stop();
void setPauseOnHeadphonesDisconnect(boolean enabled);
void setWakelockEnabled(boolean enabled);
boolean isRunning();
void registerCallback(IMainCallback cb);
Expand Down
58 changes: 58 additions & 0 deletions android/src/Main.java
Expand Up @@ -24,9 +24,13 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothClass;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
Expand Down Expand Up @@ -55,6 +59,7 @@ public class Main extends Service implements Runnable {
private String mError = null;
private final RemoteCallbackList<IMainCallback> mCallbacks = new RemoteCallbackList<IMainCallback>();
private final IBinder mBinder = new MainStub(this);
private boolean mPauseOnHeadphonesDisconnect = false;
private PowerManager.WakeLock mWakelock = null;

static class MainStub extends IMain.Stub {
Expand All @@ -68,6 +73,9 @@ public void start() {
public void stop() {
mService.stop();
}
public void setPauseOnHeadphonesDisconnect(boolean enabled) {
mService.setPauseOnHeadphonesDisconnect(enabled);
}
public void setWakelockEnabled(boolean enabled) {
mService.setWakelockEnabled(enabled);
}
Expand Down Expand Up @@ -191,6 +199,28 @@ private void start() {
if (mThread != null)
return;

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_HEADSET_PLUG);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!mPauseOnHeadphonesDisconnect) {
return;
}

if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
if (intent.hasExtra("state") && intent.getIntExtra("state", 0) == 0)
pause();
} else {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBluetoothClass().hasService(BluetoothClass.Service.AUDIO))
pause();
}
}
}, filter);

final Intent mainIntent = new Intent(this, Settings.class);
mainIntent.setAction("android.intent.action.MAIN");
mainIntent.addCategory("android.intent.category.LAUNCHER");
Expand Down Expand Up @@ -241,6 +271,21 @@ private void stop() {
stopSelf();
}

private void pause() {
if (mThread != null) {
if (mThread.isAlive()) {
synchronized (this) {
if (mStatus == MAIN_STATUS_STARTED)
Bridge.pause();
}
}
}
}

private void setPauseOnHeadphonesDisconnect(boolean enabled) {
mPauseOnHeadphonesDisconnect = enabled;
}

private void setWakelockEnabled(boolean enabled) {
if (enabled && mWakelock == null) {
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
Expand Down Expand Up @@ -368,6 +413,19 @@ public boolean stop() {
}
}

public boolean setPauseOnHeadphonesDisconnect(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.setPauseOnHeadphonesDisconnect(enabled);
return true;
} catch (RemoteException e) {
}
}
return false;
}
}

public boolean setWakelockEnabled(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
Expand Down
18 changes: 18 additions & 0 deletions android/src/Settings.java
Expand Up @@ -59,6 +59,7 @@ public class Settings extends Activity {
public static class Preferences {
public static final String KEY_RUN_ON_BOOT ="run_on_boot";
public static final String KEY_WAKELOCK ="wakelock";
public static final String KEY_PAUSE_ON_HEADPHONES_DISCONNECT ="pause_on_headphones_disconnect";

public static SharedPreferences get(Context context) {
return context.getSharedPreferences(TAG, MODE_PRIVATE);
Expand Down Expand Up @@ -154,6 +155,9 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (Preferences.getBoolean(Settings.this,
Preferences.KEY_WAKELOCK, false))
mClient.setWakelockEnabled(true);
if (Preferences.getBoolean(Settings.this,
Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false))
mClient.setPauseOnHeadphonesDisconnect(true);
} else {
mClient.stop();
}
Expand All @@ -179,6 +183,15 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
}
};

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);
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
/* TODO: this sure is the wrong place to request
Expand Down Expand Up @@ -211,6 +224,11 @@ protected void onCreate(Bundle savedInstanceState) {
if (Preferences.getBoolean(this, Preferences.KEY_WAKELOCK, false))
checkbox.setChecked(true);

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);

super.onCreate(savedInstanceState);
}

Expand Down
9 changes: 9 additions & 0 deletions src/Main.cxx
Expand Up @@ -612,6 +612,15 @@ Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass)
global_instance->Break();
}

gcc_visibility_default
JNIEXPORT void JNICALL
Java_org_musicpd_Bridge_pause(JNIEnv *, jclass)
{
if (global_instance != nullptr)
for (auto &partition : global_instance->partitions)
partition.pc.LockSetPause(true);
}

#else

static inline void
Expand Down

0 comments on commit 5768777

Please sign in to comment.