Merge branch 'mediasession' of https://github.com/DDRBoxman/MPD
This commit is contained in:
commit
3e862b85d4
|
@ -70,6 +70,8 @@ dependencies {
|
|||
ksp("com.google.dagger:dagger-compiler:2.49")
|
||||
ksp("com.google.dagger:hilt-compiler:2.49")
|
||||
|
||||
implementation("androidx.media3:media3-session:1.2.0")
|
||||
|
||||
// Android Studio Preview support
|
||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
|
|
|
@ -18,4 +18,6 @@ public class Bridge {
|
|||
public static native void run(Context context, LogListener logListener);
|
||||
public static native void shutdown();
|
||||
public static native void pause();
|
||||
public static native void playNext();
|
||||
public static native void playPrevious();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package org.musicpd;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.SimpleBasePlayer;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@UnstableApi
|
||||
public class MPDPlayer extends SimpleBasePlayer {
|
||||
|
||||
List<MediaItemData> placeholderItems;
|
||||
public MPDPlayer(Looper looper) {
|
||||
super(looper);
|
||||
|
||||
// Dummy items to let us receive next and previous commands
|
||||
MediaItemData item0 = new MediaItemData.Builder(0)
|
||||
.build();
|
||||
MediaItemData item1 = new MediaItemData.Builder(1)
|
||||
.build();
|
||||
MediaItemData item2 = new MediaItemData.Builder(2)
|
||||
.build();
|
||||
MediaItemData[] items = new MediaItemData[] { item0, item1, item2 };
|
||||
|
||||
placeholderItems = Arrays.asList(items);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected State getState() {
|
||||
Commands commands = new Commands.Builder().addAll(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM).build();
|
||||
|
||||
return new State.Builder()
|
||||
.setAvailableCommands(commands)
|
||||
.setPlaybackState(Player.STATE_READY)
|
||||
.setPlaylist(placeholderItems)
|
||||
.setCurrentMediaItemIndex(1)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@Override
|
||||
protected ListenableFuture<?> handleSeek(int mediaItemIndex, long positionMs, int seekCommand) {
|
||||
switch (seekCommand) {
|
||||
case COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM:
|
||||
case COMMAND_SEEK_TO_PREVIOUS:
|
||||
Bridge.playPrevious();
|
||||
break;
|
||||
case COMMAND_SEEK_TO_NEXT_MEDIA_ITEM:
|
||||
case COMMAND_SEEK_TO_NEXT:
|
||||
Bridge.playNext();
|
||||
break;
|
||||
}
|
||||
return Futures.immediateVoidFuture();
|
||||
}
|
||||
}
|
|
@ -16,11 +16,16 @@ import android.content.ServiceConnection;
|
|||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaSession;
|
||||
|
||||
import org.musicpd.data.LoggingRepository;
|
||||
import org.musicpd.ui.SettingsActivity;
|
||||
|
||||
|
@ -51,6 +56,8 @@ public class Main extends Service implements Runnable {
|
|||
private boolean mPauseOnHeadphonesDisconnect = false;
|
||||
private PowerManager.WakeLock mWakelock = null;
|
||||
|
||||
private MediaSession mMediaSession = null;
|
||||
|
||||
@Inject
|
||||
LoggingRepository logging;
|
||||
|
||||
|
@ -184,6 +191,7 @@ public class Main extends Service implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void start() {
|
||||
if (mThread != null)
|
||||
return;
|
||||
|
@ -225,11 +233,16 @@ public class Main extends Service implements Runnable {
|
|||
mThread = new Thread(this);
|
||||
mThread.start();
|
||||
|
||||
MPDPlayer player = new MPDPlayer(Looper.getMainLooper());
|
||||
mMediaSession = new MediaSession.Builder(this, player).build();
|
||||
|
||||
startForeground(R.string.notification_title_mpd_running, notification);
|
||||
startService(new Intent(this, Main.class));
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
mMediaSession.release();
|
||||
mMediaSession = null;
|
||||
if (mThread != null) {
|
||||
if (mThread.isAlive()) {
|
||||
synchronized (this) {
|
||||
|
|
22
src/Main.cxx
22
src/Main.cxx
|
@ -614,6 +614,28 @@ Java_org_musicpd_Bridge_pause(JNIEnv *, jclass)
|
|||
partition.pc.LockSetPause(true);
|
||||
}
|
||||
|
||||
gcc_visibility_default
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_musicpd_Bridge_playNext(JNIEnv *, jclass)
|
||||
{
|
||||
if (global_instance != nullptr)
|
||||
BlockingCall(global_instance->event_loop, [&](){
|
||||
for (auto &partition : global_instance->partitions)
|
||||
partition.PlayNext();
|
||||
});
|
||||
}
|
||||
|
||||
gcc_visibility_default
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_musicpd_Bridge_playPrevious(JNIEnv *, jclass)
|
||||
{
|
||||
if (global_instance != nullptr)
|
||||
BlockingCall(global_instance->event_loop, [&](){
|
||||
for (auto &partition : global_instance->partitions)
|
||||
partition.PlayPrevious();
|
||||
});
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
|
|
Loading…
Reference in New Issue