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 'dart:async';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:catcher_2/catcher_2.dart'; import 'package:catcher_2/catcher_2.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:media_kit/media_kit.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 // ignore: implementation_imports
import 'package:spotube/services/audio_player/playback_state.dart'; import 'package:spotube/services/audio_player/playback_state.dart';
@ -14,6 +17,13 @@ class MkPlayerWithState extends Player {
final StreamController<bool> _shuffleStream; final StreamController<bool> _shuffleStream;
final StreamController<PlaylistMode> _loopModeStream; 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; late final List<StreamSubscription> _subscriptions;
bool _shuffled; bool _shuffled;
@ -21,6 +31,9 @@ class MkPlayerWithState extends Player {
Playlist? _playlist; Playlist? _playlist;
List<Media>? _tempMedias; List<Media>? _tempMedias;
int _androidAudioSessionId = 0;
String _packageName = "";
AndroidAudioManager? _androidAudioManager;
MkPlayerWithState({super.configuration}) MkPlayerWithState({super.configuration})
: _playerStateStream = StreamController.broadcast(), : _playerStateStream = StreamController.broadcast(),
@ -64,6 +77,34 @@ class MkPlayerWithState extends Player {
Catcher2.reportCheckedError('[MediaKitError] \n$event', null); 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; bool get shuffled => _shuffled;
@ -140,10 +181,11 @@ class MkPlayerWithState extends Player {
} }
@override @override
Future<void> dispose() { Future<void> dispose() async {
for (var element in _subscriptions) { for (var element in _subscriptions) {
element.cancel(); element.cancel();
} }
await notifyAudioSessionUpdate(false);
return super.dispose(); return super.dispose();
} }

View File

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