Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New queue playback solution #13

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
52 changes: 33 additions & 19 deletions lib/just_audio_media_kit.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// package:media_kit bindings for just_audio to support Linux and Windows.
/// `package:media_kit` bindings for `just_audio` to support Linux and Windows.
library just_audio_media_kit;

import 'dart:collection';
Expand All @@ -11,12 +11,12 @@ import 'package:media_kit/media_kit.dart';
import 'package:universal_platform/universal_platform.dart';

class JustAudioMediaKit extends JustAudioPlatform {
JustAudioMediaKit();
static final _logger = Logger('JustAudioMediaKit');

/// The internal MPV player's logLevel
/// The internal MPV player's logLevel.
static MPVLogLevel mpvLogLevel = MPVLogLevel.error;

/// Sets the demuxer's cache size (in bytes)
/// Sets the demuxer's cache size (in bytes).
static int bufferSize = 32 * 1024 * 1024;

/// Sets the name of the underlying window & process for native backend. This is visible inside the Windows' volume mixer.
Expand All @@ -40,15 +40,22 @@ class JustAudioMediaKit extends JustAudioPlatform {
/// This uses `scaletempo` under the hood & disables `audio-pitch-correction`.
static bool pitch = true;

/// Enables gapless playback via the [`--prefetch-playlist`](https://mpv.io/manual/stable/#options-prefetch-playlist) in libmpv
/// Enables gapless playback via the [`--prefetch-playlist`](https://mpv.io/manual/stable/#options-prefetch-playlist) in libmpv.
///
/// This is highly experimental. Use at your own risk.
///
/// Check [mpv's docs](https://mpv.io/manual/stable/#options-prefetch-playlist) and
/// [the related issue](https://github.com/Pato05/just_audio_media_kit/issues/11) for more information
/// [the related issue](https://github.com/Pato05/just_audio_media_kit/issues/11) for more information.
///
/// [prefetchPlaylistSize] can be changed to set the amount of items to prefetch.
static bool prefetchPlaylist = false;

static final _logger = Logger('JustAudioMediaKit');
/// Max amount of items to prefetch in the playlist.
///
/// Does nothing, if [prefetchPlaylist] is set to false. Default is 2.
/// It is not recommended to change this, because libmpv doesn't prefetch more than 2 items.
static int prefetchPlaylistSize = 2;

final _players = HashMap<String, MediaKitPlayer>();

/// Players that are disposing (player id -> future that completes when the player is disposed)
Expand All @@ -57,7 +64,7 @@ class JustAudioMediaKit extends JustAudioPlatform {
/// Initializes the plugin if the platform we're running on is marked
/// as true, otherwise it will leave everything unchanged.
///
/// Can also be safely called from Web, even though it'll have no effect
/// Can also be safely called from Web, even though it'll have no effect.
static void ensureInitialized({
bool linux = true,
bool windows = true,
Expand All @@ -69,14 +76,14 @@ class JustAudioMediaKit extends JustAudioPlatform {
/// The name of the library is generally `libmpv.so` on GNU/Linux and `libmpv-2.dll` on Windows.
String? libmpv,
}) {
if ((UniversalPlatform.isLinux && linux) ||
if (!((UniversalPlatform.isLinux && linux) ||
(UniversalPlatform.isWindows && windows) ||
(UniversalPlatform.isAndroid && android) ||
(UniversalPlatform.isIOS && iOS) ||
(UniversalPlatform.isMacOS && macOS)) {
registerWith();
MediaKit.ensureInitialized(libmpv: libmpv);
}
(UniversalPlatform.isMacOS && macOS))) return;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be done. It should be the user's choice whether to enable just_audio_media_kit to be used instead of the default plugin on macOS.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about this one... I've cleaned my code, so brackets won't confuse you:

if (!(
  (UniversalPlatform.isLinux && linux) ||
  (UniversalPlatform.isWindows && windows) ||
  (UniversalPlatform.isAndroid && android) ||
  (UniversalPlatform.isIOS && iOS) ||
  (UniversalPlatform.isMacOS && macOS)
)) return;

I haven't removed the isMacOS check, it is still present in my code. Or am I missing something here?


Basically, my code does the exact same thing as your did, but instead of this:

if (condition) {
  do_something();
}

I've changed it to this:

if (!condition) return;

do_something();

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I'm sorry, I didn't read it properly.
Though readability-wise, I liked it more my way, it's more straightforward since it's just one "if" statement, and a pretty long one, too.


registerWith();
MediaKit.ensureInitialized(libmpv: libmpv);
}

/// Registers the plugin with [JustAudioPlatform]
Expand All @@ -88,32 +95,37 @@ class JustAudioMediaKit extends JustAudioPlatform {
Future<AudioPlayerPlatform> init(InitRequest request) async {
if (_players.containsKey(request.id)) {
throw PlatformException(
code: 'error', message: 'Player ${request.id} already exists!');
code: 'error',
message: 'Player ${request.id} already exists!',
);
}

_logger.fine('instantiating new player ${request.id}');
final player = MediaKitPlayer(request.id);
_players[request.id] = player;
await player.ready();
_logger.fine('player ready! (players: $_players)');

return player;
}

@override
Future<DisposePlayerResponse> disposePlayer(
DisposePlayerRequest request) async {
Future<DisposePlayerResponse> disposePlayer(request) async {
_logger.fine('disposing player ${request.id}');

// temporary workaround because disposePlayer is called more than once
if (_disposingPlayers.containsKey(request.id)) {
_logger.fine('disposePlayer() called more than once!');
await _disposingPlayers[request.id]!;

return DisposePlayerResponse();
}

if (!_players.containsKey(request.id)) {
throw PlatformException(
code: 'error', message: 'Player ${request.id} doesn\'t exist.');
code: 'error',
message: 'Player ${request.id} doesn\'t exist.',
);
}

final future = _players[request.id]!.release();
Expand All @@ -123,17 +135,19 @@ class JustAudioMediaKit extends JustAudioPlatform {
_disposingPlayers.remove(request.id);

_logger.fine('player ${request.id} disposed!');

return DisposePlayerResponse();
}

@override
Future<DisposeAllPlayersResponse> disposeAllPlayers(
DisposeAllPlayersRequest request) async {
Future<DisposeAllPlayersResponse> disposeAllPlayers(request) async {
_logger.fine('disposing of all players...');

if (_players.isNotEmpty) {
await Future.wait(_players.values.map((e) => e.release()));
_players.clear();
}

return DisposeAllPlayersResponse();
}
}
Loading