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 trackList = []; int trackNbr = 0; int userPageNbr = 3; double currentVolume = 1; Future> 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(homeContext, listen: false); HomeProvider homeProvider = Provider.of(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(); } Future nextTrack() async { if (currentTrack != null && currentTrack!.number < trackList.last.number) { currentTrack = trackList .firstWhere((element) => element.number == currentTrack!.number + 1); await playTrack(currentTrack!); } } Future backTrack() async { if (currentTrack != null && currentTrack!.number > 1) { currentTrack = trackList .firstWhere((element) => element.number == currentTrack!.number - 1); await playTrack(currentTrack!); } } void resumePlay() { if (currentTrack == null) { currentTrack = trackList.first; playTrack(currentTrack!); } else { player.state.name == 'playing' ? player.pause() : player.resume(); } } List> get radioList { List> 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> get pageList { List> 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(); } }