158 lines
5.0 KiB
Dart
158 lines
5.0 KiB
Dart
import 'dart:convert';
|
|
import 'package:fipy/globals.dart';
|
|
import 'package:fipy/models/track.dart';
|
|
import 'package:flutter/material.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:audioplayers/audioplayers.dart';
|
|
|
|
class HomeProvider with ChangeNotifier {
|
|
Track? currentTrack;
|
|
AudioPlayer player = AudioPlayer(playerId: 'fipyPlayerID');
|
|
|
|
List<Track> trackList = [];
|
|
int trackNbr = 0;
|
|
int userPageNbr = 3;
|
|
double currentVolume = 1;
|
|
|
|
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 {
|
|
log.d('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(Track track) async {
|
|
var yt = YoutubeExplode();
|
|
PlayerProvider playerProvider =
|
|
Provider.of<PlayerProvider>(homeContext, listen: false);
|
|
HomeProvider homeProvider =
|
|
Provider.of<HomeProvider>(homeContext, listen: false);
|
|
|
|
// track = trackList[track.number - 1];
|
|
currentTrack = track;
|
|
|
|
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',
|
|
];
|
|
|
|
player.stop();
|
|
Future.delayed(const Duration(milliseconds: 5));
|
|
|
|
try {
|
|
final source = UrlSource(
|
|
"https://${invidiousUrl[3]}/latest_version?id=${track.id}&itag=140&local=true&listen=1");
|
|
log.d(source.url);
|
|
await player.play(source);
|
|
} catch (e) {
|
|
log.d('Play error: $e');
|
|
}
|
|
Future.delayed(const Duration(milliseconds: 50));
|
|
|
|
player.onDurationChanged.listen((event) async {
|
|
currentTrack!.duration = await player.getDuration();
|
|
playerProvider.reload();
|
|
});
|
|
|
|
player.onPositionChanged.listen((position) async {
|
|
currentTrack!.position = position;
|
|
playerProvider.reload();
|
|
});
|
|
|
|
player.onPlayerComplete.listen((event) {
|
|
var nextTrack =
|
|
trackList.firstWhere((element) => element.number == track.number + 1);
|
|
currentTrack = nextTrack;
|
|
playTrack(nextTrack);
|
|
});
|
|
|
|
playerProvider.reload();
|
|
homeProvider.reload();
|
|
yt.close();
|
|
}
|
|
|
|
List<DropdownMenuItem<String>> get radioList {
|
|
List<DropdownMenuItem<String>> menuItems = [
|
|
const DropdownMenuItem(value: "fip", child: Text("FIP")),
|
|
const DropdownMenuItem(value: "fip_electro", child: Text("Electro")),
|
|
const DropdownMenuItem(value: "fip_groove", child: Text("Groove")),
|
|
const DropdownMenuItem(value: "fip_rock", child: Text("Rock")),
|
|
const DropdownMenuItem(value: "fip_jazz", child: Text("Jazz")),
|
|
const DropdownMenuItem(value: "fip_pop", child: Text("Pop")),
|
|
const DropdownMenuItem(value: "fip_reggae", child: Text("Reggae")),
|
|
const DropdownMenuItem(value: "fip_world", child: Text("World")),
|
|
const DropdownMenuItem(
|
|
value: "fip_nouveautes", child: Text("Nouveautés")),
|
|
];
|
|
return menuItems;
|
|
}
|
|
|
|
List<DropdownMenuItem<String>> get pageList {
|
|
List<DropdownMenuItem<String>> menuItems = [
|
|
const DropdownMenuItem(value: "3", child: Text("25")),
|
|
const DropdownMenuItem(value: "6", child: Text("50")),
|
|
const DropdownMenuItem(value: "12", child: Text("100")),
|
|
const DropdownMenuItem(value: "25", child: Text("200")),
|
|
const DropdownMenuItem(value: "62", child: Text("500")),
|
|
];
|
|
return menuItems;
|
|
}
|
|
|
|
void reload() {
|
|
notifyListeners();
|
|
}
|
|
}
|