mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
initial ingration with audioplayers flutter plugin
seek doesn't work on Endeavour OS (Arch)
This commit is contained in:
parent
4321668806
commit
f896f65095
28
.github/workflows/feature-audioplayers.yaml
vendored
Normal file
28
.github/workflows/feature-audioplayers.yaml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: audioplayers integration build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- build
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v2.2.0
|
||||
with:
|
||||
cache: true
|
||||
- run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||
- run: flutter config --enable-linux-desktop
|
||||
- run: flutter pub get
|
||||
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
- run: flutter clean
|
||||
- run: flutter build linux
|
||||
- run: make tar
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Linux-Bundle
|
||||
path: build/Spotube-linux-x86_64.tar.xz
|
@ -12,12 +12,16 @@ All types of contributions are encouraged and valued. See the [Table of Contents
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [I Have a Question](#i-have-a-question)
|
||||
- [I Want To Contribute](#i-want-to-contribute)
|
||||
- [Reporting Bugs](#reporting-bugs)
|
||||
- [Suggesting Enhancements](#suggesting-enhancements)
|
||||
- [Your First Code Contribution](#your-first-code-contribution)
|
||||
- [Contributing to Spotube](#contributing-to-spotube)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [I Have a Question](#i-have-a-question)
|
||||
- [I Want To Contribute](#i-want-to-contribute)
|
||||
- [Reporting Bugs](#reporting-bugs)
|
||||
- [Before Submitting a Bug Report](#before-submitting-a-bug-report)
|
||||
- [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report)
|
||||
- [Suggesting Enhancements](#suggesting-enhancements)
|
||||
- [Your First Code Contribution](#your-first-code-contribution)
|
||||
|
||||
|
||||
## Code of Conduct
|
||||
@ -109,6 +113,9 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/KRTirt
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
<!-- Download -->
|
||||
audioplayers requirement https://github.com/bluefireteam/audioplayers/blob/main/packages/audioplayers_linux/requirements.md
|
||||
|
||||
Do the following:
|
||||
- Download the latest Flutter SDK (>=2.15.1) & enable desktop support
|
||||
- Install Development dependencies in linux
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@ -34,24 +35,6 @@ class Player extends HookConsumerWidget {
|
||||
final AsyncSnapshot<SharedPreferences?> localStorage =
|
||||
useFuture(future, initialData: null);
|
||||
|
||||
useEffect(() {
|
||||
/// warm up the audio player before playing actual audio
|
||||
/// It's for resolving unresolved issue related to just_audio's
|
||||
/// [disposeAllPlayers] method which is throwing
|
||||
/// [UnimplementedException] in the [PlatformInterface]
|
||||
/// implementation
|
||||
player.core.setAsset("assets/warmer.mp3");
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
useEffect(() {
|
||||
if (localStorage.hasData) {
|
||||
_volume.value = localStorage.data?.getDouble(LocalStorageKeys.volume) ??
|
||||
player.core.volume;
|
||||
}
|
||||
return null;
|
||||
}, [localStorage.data]);
|
||||
|
||||
String albumArt = useMemoized(
|
||||
() => imageToUrlString(
|
||||
playback.currentTrack?.album?.images,
|
||||
|
@ -33,7 +33,7 @@ class PlayerControls extends HookConsumerWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
StreamBuilder<Duration>(
|
||||
stream: player.core.positionStream,
|
||||
stream: player.core.onPositionChanged,
|
||||
builder: (context, snapshot) {
|
||||
final totalMinutes =
|
||||
zeroPadNumStr(duration.inMinutes.remainder(60));
|
||||
@ -48,23 +48,41 @@ class PlayerControls extends HookConsumerWidget {
|
||||
|
||||
final sliderMax = duration.inSeconds;
|
||||
final sliderValue = snapshot.data?.inSeconds ?? 0;
|
||||
// final value = (sliderMax == 0 || sliderValue > sliderMax)
|
||||
// ? 0
|
||||
// : sliderValue / sliderMax;
|
||||
|
||||
final _duration = playback.duration;
|
||||
final _position = snapshot.data;
|
||||
final value = (_position != null &&
|
||||
_duration != null &&
|
||||
_position.inMilliseconds > 0 &&
|
||||
_position.inMilliseconds < _duration.inMilliseconds)
|
||||
? _position.inMilliseconds / _duration.inMilliseconds
|
||||
: 0.0;
|
||||
return Column(
|
||||
children: [
|
||||
Slider.adaptive(
|
||||
// cannot divide by zero
|
||||
// there's an edge case for value being bigger
|
||||
// than total duration. Keeping it resolved
|
||||
value: (sliderMax == 0 || sliderValue > sliderMax)
|
||||
? 0
|
||||
: sliderValue / sliderMax,
|
||||
onChanged: (value) {},
|
||||
onChangeEnd: (value) {
|
||||
player.seek(
|
||||
Duration(
|
||||
seconds: (value * sliderMax).toInt(),
|
||||
),
|
||||
);
|
||||
value: value,
|
||||
onChanged: (v) async {
|
||||
final duration = _duration;
|
||||
if (duration == null) {
|
||||
return;
|
||||
}
|
||||
final position = v * duration.inMilliseconds;
|
||||
await player
|
||||
.seek(Duration(milliseconds: position.round()));
|
||||
},
|
||||
// onChangeEnd: (value) async {
|
||||
// await player.seek(
|
||||
// Duration(
|
||||
// seconds: (value * sliderMax).toInt(),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
activeColor: iconColor,
|
||||
),
|
||||
Padding(
|
||||
|
@ -107,10 +107,8 @@ Future<SpotubeTrack> toSpotubeTrack({
|
||||
"[YouTube Matched Track] ${ytVideo.title} | ${ytVideo.author} - ${ytVideo.url}",
|
||||
);
|
||||
|
||||
final audioManifest = (Platform.isMacOS || Platform.isIOS)
|
||||
? trackManifest.audioOnly
|
||||
.where((info) => info.codec.mimeType == "audio/mp4")
|
||||
: trackManifest.audioOnly;
|
||||
final audioManifest = trackManifest.audioOnly
|
||||
.where((info) => info.codec.mimeType == "audio/mp4");
|
||||
|
||||
final ytUri = (audioQuality == AudioQuality.high
|
||||
? audioManifest.withHighestBitrate()
|
||||
|
@ -6,7 +6,7 @@ useSyncedLyrics(WidgetRef ref, Map<int, String> lyricsMap) {
|
||||
final player = ref.watch(playbackProvider.select(
|
||||
(value) => (value.player),
|
||||
));
|
||||
final stream = player.core.positionStream;
|
||||
final stream = player.core.onPositionChanged;
|
||||
|
||||
final currentTime = useState(0);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was generated using the following command and may be overwritten.
|
||||
// dart-dbus generate-object defs/org.mpris.MediaPlayer2.Player.xml
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:dbus/dbus.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import 'package:spotube/helpers/image-to-url-string.dart';
|
||||
import 'package:spotube/models/SpotubeTrack.dart';
|
||||
import 'package:spotube/provider/Playback.dart';
|
||||
@ -19,7 +19,7 @@ class Player_Interface extends DBusObject {
|
||||
|
||||
/// Gets value of property org.mpris.MediaPlayer2.Player.PlaybackStatus
|
||||
Future<DBusMethodResponse> getPlaybackStatus() async {
|
||||
final status = player.playing
|
||||
final status = player.state == PlayerState.playing
|
||||
? "Playing"
|
||||
: playback.currentPlaylist == null
|
||||
? "Stopped"
|
||||
@ -40,12 +40,12 @@ class Player_Interface extends DBusObject {
|
||||
|
||||
/// Gets value of property org.mpris.MediaPlayer2.Player.Rate
|
||||
Future<DBusMethodResponse> getRate() async {
|
||||
return DBusMethodSuccessResponse([DBusDouble(player.speed)]);
|
||||
return DBusMethodSuccessResponse([DBusDouble(1)]);
|
||||
}
|
||||
|
||||
/// Sets property org.mpris.MediaPlayer2.Player.Rate
|
||||
Future<DBusMethodResponse> setRate(double value) async {
|
||||
player.setSpeed(value);
|
||||
player.setPlaybackRate(value);
|
||||
return DBusMethodSuccessResponse();
|
||||
}
|
||||
|
||||
@ -104,19 +104,19 @@ class Player_Interface extends DBusObject {
|
||||
|
||||
/// Gets value of property org.mpris.MediaPlayer2.Player.Volume
|
||||
Future<DBusMethodResponse> getVolume() async {
|
||||
return DBusMethodSuccessResponse([DBusDouble(player.volume)]);
|
||||
return DBusMethodSuccessResponse([DBusDouble(playback.volume)]);
|
||||
}
|
||||
|
||||
/// Sets property org.mpris.MediaPlayer2.Player.Volume
|
||||
Future<DBusMethodResponse> setVolume(double value) async {
|
||||
player.setVolume(value);
|
||||
playback.setVolume(value);
|
||||
return DBusMethodSuccessResponse();
|
||||
}
|
||||
|
||||
/// Gets value of property org.mpris.MediaPlayer2.Player.Position
|
||||
Future<DBusMethodResponse> getPosition() async {
|
||||
return DBusMethodSuccessResponse([
|
||||
DBusInt64(player.position.inMicroseconds),
|
||||
DBusInt64((await player.getDuration())?.inMicroseconds ?? 0),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ class Player_Interface extends DBusObject {
|
||||
|
||||
/// Implementation of org.mpris.MediaPlayer2.Player.PlayPause()
|
||||
Future<DBusMethodResponse> doPlayPause() async {
|
||||
player.playing ? player.pause() : player.play();
|
||||
player.state == PlayerState.playing ? player.pause() : player.resume();
|
||||
return DBusMethodSuccessResponse();
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ class Player_Interface extends DBusObject {
|
||||
|
||||
/// Implementation of org.mpris.MediaPlayer2.Player.Play()
|
||||
Future<DBusMethodResponse> doPlay() async {
|
||||
player.play();
|
||||
player.resume();
|
||||
return DBusMethodSuccessResponse();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
|
||||
final audioPlayerProvider = Provider<AudioPlayer>((ref) {
|
||||
return AudioPlayer();
|
||||
|
@ -3,11 +3,11 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:dbus/dbus.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/entities/CacheTrack.dart';
|
||||
import 'package:spotube/helpers/artist-to-string.dart';
|
||||
@ -25,7 +25,7 @@ import 'package:spotube/utils/PersistedChangeNotifier.dart';
|
||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||
|
||||
class Playback extends PersistedChangeNotifier {
|
||||
AudioSource? _currentAudioSource;
|
||||
UrlSource? _currentAudioSource;
|
||||
final _logger = getLogger(Playback);
|
||||
CurrentPlaylist? _currentPlaylist;
|
||||
Track? _currentTrack;
|
||||
@ -34,7 +34,6 @@ class Playback extends PersistedChangeNotifier {
|
||||
bool _isPlaying = false;
|
||||
Duration? duration;
|
||||
|
||||
Duration _prevPosition = Duration.zero;
|
||||
bool _shuffled = false;
|
||||
|
||||
AudioPlayerHandler player;
|
||||
@ -48,6 +47,8 @@ class Playback extends PersistedChangeNotifier {
|
||||
final Media_Player _media_player;
|
||||
late final Player_Interface _mpris;
|
||||
|
||||
double volume = 1;
|
||||
|
||||
Playback({
|
||||
required this.player,
|
||||
required this.youtube,
|
||||
@ -71,8 +72,8 @@ class Playback extends PersistedChangeNotifier {
|
||||
}
|
||||
|
||||
StreamSubscription<Duration?>? _durationStream;
|
||||
StreamSubscription<PlayerState>? _playingStream;
|
||||
StreamSubscription<Duration>? _positionStream;
|
||||
StreamSubscription<bool>? _playingStream;
|
||||
|
||||
void _init() async {
|
||||
// dbus m.p.r.i.s stuff
|
||||
@ -90,60 +91,40 @@ class Playback extends PersistedChangeNotifier {
|
||||
|
||||
cacheTrackBox = await Hive.openLazyBox<CacheTrack>("track-cache");
|
||||
|
||||
_playingStream = player.core.playingStream.listen(
|
||||
(playing) {
|
||||
_isPlaying = playing;
|
||||
_playingStream = player.core.onPlayerStateChanged.listen(
|
||||
(state) async {
|
||||
_isPlaying = state == PlayerState.playing;
|
||||
if (state == PlayerState.completed) {
|
||||
if (_currentTrack?.id != null) {
|
||||
movePlaylistPositionBy(1);
|
||||
} else {
|
||||
_isPlaying = false;
|
||||
duration = null;
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
|
||||
_durationStream = player.core.durationStream.listen((event) async {
|
||||
if (event != null) {
|
||||
// Actually things doesn't work all the time as they were
|
||||
// described. So instead of listening to a `_ready`
|
||||
// stream, it has to listen to duration stream since duration
|
||||
// is always added to the Stream sink after all icyMetadata has
|
||||
// been loaded thus indicating buffering started
|
||||
if (event != Duration.zero && event != duration) {
|
||||
// this line is for prev/next or already playing playlist
|
||||
if (player.core.playing) await player.pause();
|
||||
await player.play();
|
||||
}
|
||||
duration = event;
|
||||
notifyListeners();
|
||||
}
|
||||
_durationStream = player.core.onDurationChanged.listen((event) {
|
||||
duration = event;
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
_positionStream =
|
||||
player.core.createPositionStream().listen((position) async {
|
||||
// detecting multiple same call
|
||||
if (_prevPosition.inSeconds == position.inSeconds) return;
|
||||
_prevPosition = position;
|
||||
|
||||
/// Because of ProcessingState.complete never gets set bug using a
|
||||
/// custom solution to know when the audio stops playing
|
||||
///
|
||||
/// Details: https://github.com/KRTirtho/spotube/issues/46
|
||||
if (duration != Duration.zero &&
|
||||
duration?.isNegative == false &&
|
||||
position.inSeconds == duration?.inSeconds) {
|
||||
if (_currentTrack?.id != null) {
|
||||
await player.pause();
|
||||
movePlaylistPositionBy(1);
|
||||
} else {
|
||||
_isPlaying = false;
|
||||
duration = null;
|
||||
notifyListeners();
|
||||
}
|
||||
_positionStream = player.core.onPositionChanged.listen((pos) async {
|
||||
if (pos > Duration.zero &&
|
||||
(duration == null || duration == Duration.zero)) {
|
||||
duration = await player.core.getDuration();
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_positionStream?.cancel();
|
||||
_playingStream?.cancel();
|
||||
_durationStream?.cancel();
|
||||
_positionStream?.cancel();
|
||||
cacheTrackBox?.close();
|
||||
dbus.unregisterObject(_media_player);
|
||||
dbus.unregisterObject(_mpris);
|
||||
@ -180,6 +161,12 @@ class Playback extends PersistedChangeNotifier {
|
||||
updatePersistence(clearNullEntries: true);
|
||||
}
|
||||
|
||||
void setVolume(double newVolume) {
|
||||
volume = newVolume;
|
||||
notifyListeners();
|
||||
updatePersistence();
|
||||
}
|
||||
|
||||
/// sets the provided id matched track's uri\
|
||||
/// Doesn't notify listeners\
|
||||
/// @returns `bool` - `true` if succeed & `false` when failed
|
||||
@ -238,11 +225,10 @@ class Playback extends PersistedChangeNotifier {
|
||||
);
|
||||
player.addItem(tag);
|
||||
if (parsedUri != null && parsedUri.hasAbsolutePath) {
|
||||
_currentAudioSource = AudioSource.uri(parsedUri);
|
||||
_currentAudioSource = UrlSource(parsedUri.toString());
|
||||
await player.core
|
||||
.setAudioSource(
|
||||
.play(
|
||||
_currentAudioSource!,
|
||||
preload: true,
|
||||
)
|
||||
.then((value) async {
|
||||
_currentTrack = track;
|
||||
@ -262,11 +248,10 @@ class Playback extends PersistedChangeNotifier {
|
||||
);
|
||||
if (setTrackUriById(track.id!, spotubeTrack.ytUri)) {
|
||||
logger.v("[Track Direct Source] - ${spotubeTrack.ytUri}");
|
||||
_currentAudioSource = AudioSource.uri(Uri.parse(spotubeTrack.ytUri));
|
||||
_currentAudioSource = UrlSource(spotubeTrack.ytUri);
|
||||
await player.core
|
||||
.setAudioSource(
|
||||
.play(
|
||||
_currentAudioSource!,
|
||||
preload: true,
|
||||
)
|
||||
.then((value) {
|
||||
_currentTrack = spotubeTrack;
|
||||
@ -304,13 +289,14 @@ class Playback extends PersistedChangeNotifier {
|
||||
_currentTrack = Track.fromJson(jsonDecode(map["currentTrack"]));
|
||||
startPlaying().then((_) {
|
||||
Timer.periodic(const Duration(milliseconds: 100), (timer) {
|
||||
if (player.core.playing) {
|
||||
if (player.core.state == PlayerState.playing) {
|
||||
player.pause();
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
volume = map["volume"] ?? volume;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -321,6 +307,7 @@ class Playback extends PersistedChangeNotifier {
|
||||
: null,
|
||||
"currentTrack":
|
||||
currentTrack != null ? jsonEncode(currentTrack?.toJson()) : null,
|
||||
"volume": volume,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
|
||||
/// An [AudioHandler] for playing a single item.
|
||||
class AudioPlayerHandler extends BaseAudioHandler {
|
||||
@ -15,7 +15,16 @@ class AudioPlayerHandler extends BaseAudioHandler {
|
||||
// So that our clients (the Flutter UI and the system notification) know
|
||||
// what state to display, here we set up our audio handler to broadcast all
|
||||
// playback state changes as they happen via playbackState...
|
||||
_player.playbackEventStream.map(_transformEvent).pipe(playbackState);
|
||||
// _player.
|
||||
_player.onPlayerStateChanged.listen((state) async {
|
||||
playbackState.add(await _transformEvent());
|
||||
});
|
||||
_player.onDurationChanged.listen((duration) async {
|
||||
playbackState.add(await _transformEvent());
|
||||
});
|
||||
_player.onPositionChanged.listen((state) async {
|
||||
playbackState.add(await _transformEvent());
|
||||
});
|
||||
}
|
||||
|
||||
AudioPlayer get core => _player;
|
||||
@ -30,7 +39,7 @@ class AudioPlayerHandler extends BaseAudioHandler {
|
||||
// your audio playback logic in one place.
|
||||
|
||||
@override
|
||||
Future<void> play() => _player.play();
|
||||
Future<void> play() => _player.resume();
|
||||
|
||||
@override
|
||||
Future<void> pause() => _player.pause();
|
||||
@ -64,27 +73,20 @@ class AudioPlayerHandler extends BaseAudioHandler {
|
||||
/// This method is used from the constructor. Every event received from the
|
||||
/// just_audio player will be transformed into an audio_service state so that
|
||||
/// it can be broadcast to audio_service clients.
|
||||
PlaybackState _transformEvent(PlaybackEvent event) {
|
||||
Future<PlaybackState> _transformEvent() async {
|
||||
return PlaybackState(
|
||||
controls: [
|
||||
MediaControl.skipToPrevious,
|
||||
if (_player.playing) MediaControl.pause else MediaControl.play,
|
||||
if (_player.state == PlayerState.playing)
|
||||
MediaControl.pause
|
||||
else
|
||||
MediaControl.play,
|
||||
MediaControl.skipToNext,
|
||||
MediaControl.stop,
|
||||
],
|
||||
androidCompactActionIndices: const [0, 1, 2],
|
||||
processingState: const {
|
||||
ProcessingState.idle: AudioProcessingState.idle,
|
||||
ProcessingState.loading: AudioProcessingState.loading,
|
||||
ProcessingState.buffering: AudioProcessingState.buffering,
|
||||
ProcessingState.ready: AudioProcessingState.ready,
|
||||
ProcessingState.completed: AudioProcessingState.completed,
|
||||
}[_player.processingState]!,
|
||||
playing: _player.playing,
|
||||
updatePosition: _player.position,
|
||||
bufferedPosition: _player.bufferedPosition,
|
||||
speed: _player.speed,
|
||||
queueIndex: event.currentIndex,
|
||||
playing: _player.state == PlayerState.playing,
|
||||
updatePosition: (await _player.getCurrentPosition()) ?? Duration.zero,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,17 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
||||
#include <libwinmedia/libwinmedia_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
|
||||
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
|
||||
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) libwinmedia_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "LibwinmediaPlugin");
|
||||
libwinmedia_plugin_register_with_registrar(libwinmedia_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
@ -3,8 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_linux
|
||||
bitsdojo_window_linux
|
||||
libwinmedia
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
@ -7,8 +7,8 @@ import Foundation
|
||||
|
||||
import audio_service
|
||||
import audio_session
|
||||
import audioplayers_darwin
|
||||
import bitsdojo_window_macos
|
||||
import just_audio
|
||||
import package_info_plus_macos
|
||||
import path_provider_macos
|
||||
import shared_preferences_macos
|
||||
@ -18,8 +18,8 @@ import url_launcher_macos
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
||||
BitsdojoWindowPlugin.register(with: registry.registrar(forPlugin: "BitsdojoWindowPlugin"))
|
||||
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
|
84
pubspec.lock
84
pubspec.lock
@ -71,6 +71,55 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.6+1"
|
||||
audioplayers:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: audioplayers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
audioplayers_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
audioplayers_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_darwin
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
audioplayers_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
audioplayers_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
audioplayers_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
audioplayers_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
bitsdojo_window:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -499,41 +548,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.5.0"
|
||||
just_audio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: just_audio
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.21"
|
||||
just_audio_libwinmedia:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: just_audio_libwinmedia
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4"
|
||||
just_audio_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
just_audio_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.7"
|
||||
libwinmedia:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: libwinmedia
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.7"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -42,8 +42,6 @@ dependencies:
|
||||
url_launcher: ^6.0.17
|
||||
youtube_explode_dart: ^1.10.8
|
||||
bitsdojo_window: ^0.1.2
|
||||
just_audio: ^0.9.18
|
||||
just_audio_libwinmedia: ^0.0.4
|
||||
path: ^1.8.0
|
||||
path_provider: ^2.0.8
|
||||
collection: ^1.15.0
|
||||
@ -64,6 +62,7 @@ dependencies:
|
||||
hive: ^2.2.2
|
||||
hive_flutter: ^1.1.0
|
||||
dbus: ^0.7.3
|
||||
audioplayers: ^1.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -6,16 +6,16 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
||||
#include <libwinmedia/libwinmedia_plugin.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AudioplayersWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||
BitsdojoWindowPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
|
||||
LibwinmediaPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LibwinmediaPlugin"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
@ -3,8 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_windows
|
||||
bitsdojo_window_windows
|
||||
libwinmedia
|
||||
permission_handler_windows
|
||||
url_launcher_windows
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user