mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: windows OS media control panel support
This commit is contained in:
parent
06a043764d
commit
f0b426ae89
@ -11,6 +11,7 @@ import 'package:spotube/provider/user_preferences_provider.dart';
|
|||||||
import 'package:spotube/services/audio_player.dart';
|
import 'package:spotube/services/audio_player.dart';
|
||||||
import 'package:spotube/services/linux_audio_service.dart';
|
import 'package:spotube/services/linux_audio_service.dart';
|
||||||
import 'package:spotube/services/mobile_audio_service.dart';
|
import 'package:spotube/services/mobile_audio_service.dart';
|
||||||
|
import 'package:spotube/services/windows_audio_service.dart';
|
||||||
import 'package:spotube/utils/persisted_state_notifier.dart';
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||||
@ -137,6 +138,7 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
|
|||||||
final Ref ref;
|
final Ref ref;
|
||||||
MobileAudioService? mobileService;
|
MobileAudioService? mobileService;
|
||||||
LinuxAudioService? linuxService;
|
LinuxAudioService? linuxService;
|
||||||
|
WindowsAudioService? windowsService;
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
StateNotifierProvider<PlaylistQueueNotifier, PlaylistQueue?>(
|
StateNotifierProvider<PlaylistQueueNotifier, PlaylistQueue?>(
|
||||||
@ -166,6 +168,9 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
|
|||||||
if (kIsLinux) {
|
if (kIsLinux) {
|
||||||
linuxService = LinuxAudioService(ref, this);
|
linuxService = LinuxAudioService(ref, this);
|
||||||
}
|
}
|
||||||
|
if (kIsWindows) {
|
||||||
|
windowsService = WindowsAudioService(ref, this);
|
||||||
|
}
|
||||||
addListener((state) {
|
addListener((state) {
|
||||||
linuxService?.player.updateProperties();
|
linuxService?.player.updateProperties();
|
||||||
});
|
});
|
||||||
@ -363,6 +368,7 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
|
|||||||
duration: state!.activeTrack.duration,
|
duration: state!.activeTrack.duration,
|
||||||
);
|
);
|
||||||
mobileService?.addItem(mediaItem);
|
mobileService?.addItem(mediaItem);
|
||||||
|
windowsService?.addTrack(state!.activeTrack);
|
||||||
if (state!.activeTrack is LocalTrack) {
|
if (state!.activeTrack is LocalTrack) {
|
||||||
await audioPlayer.play(
|
await audioPlayer.play(
|
||||||
DeviceFileSource((state!.activeTrack as LocalTrack).path),
|
DeviceFileSource((state!.activeTrack as LocalTrack).path),
|
||||||
@ -512,6 +518,12 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return state?.toJson() ?? {};
|
return state?.toJson() ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
windowsService?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VolumeProvider extends PersistedStateNotifier<double> {
|
class VolumeProvider extends PersistedStateNotifier<double> {
|
||||||
|
99
lib/services/windows_audio_service.dart
Normal file
99
lib/services/windows_audio_service.dart
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:audioplayers/audioplayers.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:smtc_windows/smtc_windows.dart';
|
||||||
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/provider/playlist_queue_provider.dart';
|
||||||
|
import 'package:spotube/services/audio_player.dart';
|
||||||
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||||
|
|
||||||
|
class WindowsAudioService {
|
||||||
|
final SMTCWindows smtc;
|
||||||
|
final Ref ref;
|
||||||
|
final PlaylistQueueNotifier playlistNotifier;
|
||||||
|
|
||||||
|
final subscriptions = <StreamSubscription>[];
|
||||||
|
|
||||||
|
WindowsAudioService(this.ref, this.playlistNotifier) : smtc = SMTCWindows() {
|
||||||
|
smtc.setPlaybackStatus(PlaybackStatus.Stopped);
|
||||||
|
final buttonStream = smtc.buttonPressStream.listen((event) {
|
||||||
|
switch (event) {
|
||||||
|
case PressedButton.play:
|
||||||
|
playlistNotifier.resume();
|
||||||
|
break;
|
||||||
|
case PressedButton.pause:
|
||||||
|
playlistNotifier.pause();
|
||||||
|
break;
|
||||||
|
case PressedButton.next:
|
||||||
|
playlistNotifier.next();
|
||||||
|
break;
|
||||||
|
case PressedButton.previous:
|
||||||
|
playlistNotifier.previous();
|
||||||
|
break;
|
||||||
|
case PressedButton.stop:
|
||||||
|
playlistNotifier.stop();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final playerStateStream =
|
||||||
|
audioPlayer.onPlayerStateChanged.listen((state) async {
|
||||||
|
switch (state) {
|
||||||
|
case PlayerState.playing:
|
||||||
|
await smtc.setPlaybackStatus(PlaybackStatus.Playing);
|
||||||
|
break;
|
||||||
|
case PlayerState.paused:
|
||||||
|
await smtc.setPlaybackStatus(PlaybackStatus.Paused);
|
||||||
|
break;
|
||||||
|
case PlayerState.stopped:
|
||||||
|
await smtc.setPlaybackStatus(PlaybackStatus.Stopped);
|
||||||
|
break;
|
||||||
|
case PlayerState.completed:
|
||||||
|
await smtc.setPlaybackStatus(PlaybackStatus.Changing);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final positionStream = audioPlayer.onPositionChanged.listen((pos) async {
|
||||||
|
await smtc.setPosition(pos);
|
||||||
|
});
|
||||||
|
|
||||||
|
final durationStream =
|
||||||
|
audioPlayer.onDurationChanged.listen((duration) async {
|
||||||
|
await smtc.setEndTime(duration);
|
||||||
|
});
|
||||||
|
|
||||||
|
subscriptions.addAll([
|
||||||
|
buttonStream,
|
||||||
|
playerStateStream,
|
||||||
|
positionStream,
|
||||||
|
durationStream,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> addTrack(Track track) async {
|
||||||
|
await smtc.updateMetadata(MusicMetadata(
|
||||||
|
title: track.name!,
|
||||||
|
albumArtist: track.artists?.first.name ?? "Unknown",
|
||||||
|
artist: TypeConversionUtils.artists_X_String<Artist>(track.artists ?? []),
|
||||||
|
album: track.album?.name ?? "Unknown",
|
||||||
|
trackNumber: track.trackNumber ?? 0,
|
||||||
|
thumbnail: TypeConversionUtils.image_X_UrlString(
|
||||||
|
track.album?.images ?? [],
|
||||||
|
placeholder: ImagePlaceholder.albumArt,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
smtc.dispose();
|
||||||
|
for (var element in subscriptions) {
|
||||||
|
element.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1452,6 +1452,13 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.99"
|
version: "0.0.99"
|
||||||
|
smtc_windows:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "../smtc_windows/packages/smtc_windows"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "0.0.1"
|
||||||
source_gen:
|
source_gen:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -84,6 +84,8 @@ dependencies:
|
|||||||
youtube_explode_dart: ^1.12.1
|
youtube_explode_dart: ^1.12.1
|
||||||
flutter_desktop_tools:
|
flutter_desktop_tools:
|
||||||
path: ../flutter_desktop_tools
|
path: ../flutter_desktop_tools
|
||||||
|
smtc_windows:
|
||||||
|
path: ../smtc_windows/packages/smtc_windows
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.3.2
|
build_runner: ^2.3.2
|
||||||
|
@ -18,6 +18,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
metadata_god
|
metadata_god
|
||||||
|
smtc_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
Loading…
Reference in New Issue
Block a user