spotube/lib/services/audio_player/audio_player.dart
Alessio fece073def This pull request primarily involves the removal of several configuration files and assets, as well as minor updates to documentation. The most significant changes are the deletion of various .vscode configuration files and the removal of unused assets from the project.
Configuration File Removals:

    .vscode/c_cpp_properties.json: Removed the entire configuration for C/C++ properties.
    .vscode/launch.json: Removed the Dart launch configurations for different environments and modes.
    .vscode/settings.json: Removed settings related to CMake, spell checking, file nesting, and Dart Flutter SDK path.
    .vscode/snippets.code-snippets: Removed code snippets for Dart, including PaginatedState and PaginatedNotifier templates.
    .vscode/tasks.json: Removed the tasks configuration file.

Documentation Updates:

    CONTRIBUTION.md: Removed heart emoji from the introductory text.
    README.md: Updated the logo image and made minor text adjustments, including removing emojis and updating section titles. [1] [2] [3] [4] [5]

Asset Removals:

    lib/collections/assets.gen.dart: Removed multiple unused asset references, including images related to Spotube logos and banners. [1] [2] [3]

Minor Code Cleanups:

    cli/commands/build/linux.dart, cli/commands/build/windows.dart, cli/commands/translated.dart, cli/commands/untranslated.dart: Adjusted import statements for consistency. [1] [2] [3] [4]
    integration_test/app_test.dart: Removed an unnecessary blank line.
    lib/collections/routes.dart: Commented out the TrackRoute configuration.
2025-04-13 18:40:37 +02:00

162 lines
4.1 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:media_kit/media_kit.dart' as mk;
import 'package:media_kit/media_kit.dart' hide Track;
import 'package:spotify/spotify.dart' hide Playlist;
import 'package:spotube/models/local_track.dart';
import 'package:spotube/services/audio_player/custom_player.dart';
import 'package:spotube/services/audio_player/playback_state.dart';
import 'package:spotube/services/logger/logger.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart';
import 'package:spotube/utils/platform.dart';
part 'audio_player_impl.dart';
part 'audio_players_streams_mixin.dart';
class SpotubeMedia extends mk.Media {
final Track track;
static int serverPort = 0;
SpotubeMedia(
this.track, {
Map<String, dynamic>? extras,
super.httpHeaders,
}) : super(
track is LocalTrack
? track.path
: "http://${kIsWindows ? "localhost" : InternetAddress.anyIPv4.address}:$serverPort/stream/${track.id}",
extras: {
...?extras,
"track": switch (track) {
LocalTrack() => track.toJson(),
SourcedTrack() => track.toJson(),
_ => track.toJson(),
},
},
);
@override
String get uri {
return switch (track) {
/// [super.uri] must be used instead of [track.path] to prevent wrong
/// path format exceptions in Windows causing [extras] to be null
LocalTrack() => super.uri,
_ =>
"http://${kIsWindows ? "localhost" : InternetAddress.anyIPv4.address}:"
"$serverPort/stream/${track.id}",
};
}
factory SpotubeMedia.fromMedia(mk.Media media) {
final track = media.uri.startsWith("http")
? Track.fromJson(media.extras?["track"])
: LocalTrack.fromJson(media.extras?["track"]);
return SpotubeMedia(
track,
extras: media.extras,
httpHeaders: media.httpHeaders,
);
}
@override
operator == (Object other) {
if (other is! SpotubeMedia) return false;
final isLocal = track is LocalTrack && other.track is LocalTrack;
return isLocal
? (other.track as LocalTrack).path == (track as LocalTrack).path
: other.track.id == track.id;
}
@override
int get hashCode => track is LocalTrack
? (track as LocalTrack).path.hashCode
: track.id.hashCode;
}
abstract class AudioPlayerInterface {
final CustomPlayer _mkPlayer;
AudioPlayerInterface()
: _mkPlayer = CustomPlayer(
configuration: const mk.PlayerConfiguration(
title: "Spotube",
logLevel: kDebugMode ? mk.MPVLogLevel.info : mk.MPVLogLevel.error,
),
) {
_mkPlayer.stream.error.listen((event) {
AppLogger.reportError(event, StackTrace.current);
});
}
/// Whether the current platform supports the audioplayers plugin
static const bool _mkSupportedPlatform = true;
bool get mkSupportedPlatform => _mkSupportedPlatform;
Duration get duration {
return _mkPlayer.state.duration;
}
Playlist get playlist {
return _mkPlayer.state.playlist;
}
Duration get position {
return _mkPlayer.state.position;
}
Duration get bufferedPosition {
return _mkPlayer.state.buffer;
}
Future<mk.AudioDevice> get selectedDevice async {
return _mkPlayer.state.audioDevice;
}
Future<List<mk.AudioDevice>> get devices async {
return _mkPlayer.state.audioDevices;
}
bool get hasSource {
return _mkPlayer.state.playlist.medias.isNotEmpty;
}
// states
bool get isPlaying {
return _mkPlayer.state.playing;
}
bool get isPaused {
return !_mkPlayer.state.playing;
}
bool get isStopped {
return !hasSource;
}
Future<bool> get isCompleted async {
return _mkPlayer.state.completed;
}
bool get isShuffled {
return _mkPlayer.shuffled;
}
PlaylistMode get loopMode {
return _mkPlayer.state.playlistMode;
}
/// Returns the current volume of the player, between 0 and 1
double get volume {
return _mkPlayer.state.volume / 100;
}
bool get isBuffering {
return _mkPlayer.state.buffering;
}
}