Skip to content

Commit

Permalink
fix(android): audio issue when screen is off and broadcast audio sess…
Browse files Browse the repository at this point in the history
…ion 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. #571

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

---------

Co-authored-by: Kingkor Roy Tirtho <[email protected]>
  • Loading branch information
olivier2 and KRTirtho authored Feb 25, 2024
1 parent a850ed2 commit 17105a6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
46 changes: 44 additions & 2 deletions lib/services/audio_player/mk_state_player.dart
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -14,13 +17,23 @@ 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;
PlaylistMode _loopMode;

Playlist? _playlist;
List<Media>? _tempMedias;
int _androidAudioSessionId = 0;
String _packageName = "";
AndroidAudioManager? _androidAudioManager;

MkPlayerWithState({super.configuration})
: _playerStateStream = StreamController.broadcast(),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 17105a6

Please sign in to comment.