fix(android): audio issue when screen is off and broadcast audio session id (#1221 & #1247)

* this change fixes the garbled audio on my Pixel 6a while the screen is off. Not familiar with libmpv, but seems to favor audiotrack audio output over opensles. KRTirtho/spotube#571

* get audio session id, send it to AudioTrack in libmpv, broadcast it to other apps. Fixes KRTirtho/spotube#1221

---------

Co-authored-by: Kingkor Roy Tirtho <krtirtho@gmail.com>
This commit is contained in:
olivier2 2024-02-25 11:26:06 -05:00 committed by GitHub
parent a850ed270b
commit 17105a640b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 2 deletions

View File

@ -1,8 +1,11 @@
import 'dart:async';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:catcher_2/catcher_2.dart';
import 'package:collection/collection.dart';
import 'package:media_kit/media_kit.dart';
import 'package:flutter_broadcasts/flutter_broadcasts.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:audio_session/audio_session.dart';
// ignore: implementation_imports
import 'package:spotube/services/audio_player/playback_state.dart';
@ -14,6 +17,13 @@ class MkPlayerWithState extends Player {
final StreamController<bool> _shuffleStream;
final StreamController<PlaylistMode> _loopModeStream;
static const String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
static const String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
static const String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
static const String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
late final List<StreamSubscription> _subscriptions;
bool _shuffled;
@ -21,6 +31,9 @@ class MkPlayerWithState extends Player {
Playlist? _playlist;
List<Media>? _tempMedias;
int _androidAudioSessionId = 0;
String _packageName = "";
AndroidAudioManager? _androidAudioManager;
MkPlayerWithState({super.configuration})
: _playerStateStream = StreamController.broadcast(),
@ -64,6 +77,34 @@ class MkPlayerWithState extends Player {
Catcher2.reportCheckedError('[MediaKitError] \n$event', null);
}),
];
PackageInfo.fromPlatform().then((packageInfo) {
_packageName = packageInfo.packageName;
});
if (DesktopTools.platform.isAndroid) {
_androidAudioManager = AndroidAudioManager();
AudioSession.instance.then((s) async {
_androidAudioSessionId =
await _androidAudioManager!.generateAudioSessionId();
notifyAudioSessionUpdate(true);
nativePlayer.setProperty(
"audiotrack-session-id", _androidAudioSessionId.toString());
nativePlayer.setProperty("ao", "audiotrack,opensles,");
});
}
}
Future<void> notifyAudioSessionUpdate(bool active) async {
if (DesktopTools.platform.isAndroid) {
sendBroadcast(BroadcastMessage(
name: active
? ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION
: ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION,
data: {
EXTRA_AUDIO_SESSION: _androidAudioSessionId,
EXTRA_PACKAGE_NAME: _packageName
}));
}
}
bool get shuffled => _shuffled;
@ -140,10 +181,11 @@ class MkPlayerWithState extends Player {
}
@override
Future<void> dispose() {
Future<void> dispose() async {
for (var element in _subscriptions) {
element.cancel();
}
await notifyAudioSessionUpdate(false);
return super.dispose();
}

View File

@ -124,6 +124,7 @@ dependencies:
app_links: ^3.5.0
win32_registry: ^1.1.2
flutter_sharing_intent: ^1.1.0
flutter_broadcasts: ^0.4.0
freezed_annotation: ^2.4.1
dev_dependencies: