fipy/lib/providers/home.dart

235 lines
7.5 KiB
Dart

// ignore_for_file: avoid_print
import 'dart:convert';
import 'package:ffmpeg_cli/ffmpeg_cli.dart';
import 'package:fipy/globals.dart';
import 'package:flutter/foundation.dart';
import 'package:universal_io/io.dart';
import 'package:fipy/models/track.dart';
import 'package:flutter/material.dart';
import 'package:kplayer/kplayer.dart';
import 'package:path_provider/path_provider.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
import 'package:fipy/providers/player.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart';
// import 'package:kplayer_with_audioplayers/kplayer_with_audioplayers.dart' as kp;
class HomeProvider with ChangeNotifier {
Track? currentTrack;
PlayerController? player;
List<Track> trackList = [];
int trackNbr = 0;
int userPageNbr = 3;
Future<List<Track>> getTracks(String radio, {String cursor = ''}) async {
int pageNbr = 0;
trackList.clear();
trackNbr = 0;
bool stop = false;
while (pageNbr < userPageNbr && !stop) {
final req = Uri.parse(
'${proxyHeader}www.radiofrance.fr:443/api/v1.7/stations/fip/webradios/$radio/songs?pageCursor=$cursor');
final res = await get(req, headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
'Content-Type': 'text/plain'
});
if (res.statusCode == 200) {
Map body = jsonDecode(res.body);
if (body['next'] != null) {
cursor = body['next'];
} else {
print('Page N°$pageNbr');
stop = true;
}
for (Map track in body['songs']) {
trackNbr++;
final String title = track['secondLine'] ?? '';
final String artiste = track['firstLine'] ?? '';
final String album = track['release']['title'] ?? '';
final String image = track['visual']?['preview'] ?? '';
final String imageUrl = track['visual']?['src'] ?? '';
final thisTrack = Track(
number: trackNbr,
title: title,
artiste: artiste,
album: album,
image: image,
imageUrl: imageUrl);
trackList.add(thisTrack);
}
pageNbr++;
} else {
throw "Unable to retrieve tracks.";
}
}
return trackList;
}
Future playTrack(BuildContext context, Track track) async {
var yt = YoutubeExplode();
PlayerProvider playerProvider =
Provider.of<PlayerProvider>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
// track = trackList[track.number - 1];
currentTrack = track;
final currentVolume = player?.volume ?? 1;
if (player?.playing ?? false) player?.stop();
Future.delayed(const Duration(milliseconds: 5));
if (track.id == null) {
final secondMatch = track.artiste == '' ? track.album : track.artiste;
final resultUrl = await yt.search
.search(track.title + ' ' + secondMatch!, filter: TypeFilters.video);
track.id = resultUrl.first.id.value;
}
const invidiousUrl = [
'yewtu.be',
'vid.puffyan.us',
'invidious.snopyta.org',
'invidious.fdn.fr',
];
// final media = PlayerMedia(
// type: PlayerMediaType.network,
// resource:
// "https://${invidiousUrl[0]}/latest_version?id=${track.id}&itag=140&local=true&listen=1");
// player = kp.Player(media: media);
player = Player.network(
"https://${invidiousUrl[0]}/latest_version?id=${track.id}&itag=140&local=true&listen=1"); // https://${invidiousUrl[0]}/embed/${track.id}?listen=1&raw=1&local=true
player!.init();
print(player!.media.resource);
player!.volume = currentVolume;
try {
player!.play();
} catch (e) {
print('Play error: ' + e.toString());
}
Future.delayed(const Duration(milliseconds: 500));
player!.callback = (PlayerEvent event) {
print(event.name);
if (event.name == 'position') {
currentTrack!.duration = player!.duration;
playerProvider.reload();
}
if (event.name == 'status' && player!.position == player!.duration) {
var nextTrack = trackList
.firstWhere((element) => element.number == track.number + 1);
playTrack(context, nextTrack);
}
};
playerProvider.reload();
homeProvider.reload();
yt.close();
}
Future downloadMusic(BuildContext context, Track track) async {
var yt = YoutubeExplode();
var manifest = await yt.videos.streamsClient.getManifest(track.id);
var streamManifest = StreamManifest(manifest.streams);
var streamInfo = streamManifest.audioOnly.withHighestBitrate();
var stream = yt.videos.streamsClient.get(streamInfo);
final fileName = '${track.title} - ${track.artiste}'
.replaceAll('\\', '')
.replaceAll('/', '')
.replaceAll(':', '')
.replaceAll('*', '')
.replaceAll('?', '')
.replaceAll('"', '')
.replaceAll('<', '')
.replaceAll('>', '')
.replaceAll('|', '');
if (!kIsWeb) {
final filePath = Platform.isAndroid
? Directory('/storage/emulated/0/Download')
: await getDownloadsDirectory();
var file = File('${filePath!.path}/$fileName.webm');
var fileStream = file.openWrite();
await stream.pipe(fileStream);
await fileStream.flush();
await fileStream.close();
yt.close();
// convertToMp3(file.path);
track.file = file;
print(file.path);
}
}
List<DropdownMenuItem<String>> get radioList {
List<DropdownMenuItem<String>> menuItems = [
const DropdownMenuItem(child: Text("FIP"), value: "fip"),
const DropdownMenuItem(child: Text("Electro"), value: "fip_electro"),
const DropdownMenuItem(child: Text("Groove"), value: "fip_groove"),
const DropdownMenuItem(child: Text("Rock"), value: "fip_rock"),
const DropdownMenuItem(child: Text("Jazz"), value: "fip_jazz"),
const DropdownMenuItem(child: Text("Pop"), value: "fip_pop"),
const DropdownMenuItem(child: Text("Reggae"), value: "fip_reggae"),
const DropdownMenuItem(child: Text("World"), value: "fip_world"),
const DropdownMenuItem(
child: Text("Nouveautés"), value: "fip_nouveautes"),
];
return menuItems;
}
List<DropdownMenuItem<String>> get pageList {
List<DropdownMenuItem<String>> menuItems = [
const DropdownMenuItem(child: Text("25"), value: "3"),
const DropdownMenuItem(child: Text("50"), value: "6"),
const DropdownMenuItem(child: Text("100"), value: "12"),
const DropdownMenuItem(child: Text("200"), value: "25"),
const DropdownMenuItem(child: Text("500"), value: "62"),
];
return menuItems;
}
void reload() {
notifyListeners();
}
}
class DownloadProvider with ChangeNotifier {
void reload() {
notifyListeners();
}
}
Future convertToMp3(String audioFile) async {
audioFile = 'E:\\Téléchargements/test.webm';
final command = FfmpegCommand(
inputs: [FfmpegInput.asset(audioFile)],
args: [
// CliArg(name: 'i', value: audioFile),
const CliArg(name: 'ab', value: '320'),
const CliArg(name: 'ar', value: '44100'),
],
filterGraph: const FilterGraph(
chains: [
FilterChain(
inputs: [],
filters: [],
outputs: [],
),
],
),
outputFilepath: "E:\\Téléchargements/test.mp3",
);
// Execute command
await Ffmpeg().run(command);
}