Skip to content

Commit

Permalink
made some bug fixes in song loading
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikh Haziq committed Jan 15, 2025
1 parent 44c460b commit 38b1e7e
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 131 deletions.
2 changes: 1 addition & 1 deletion lib/app_config.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AppConfig appConfig = AppConfig(version: 36, codeName: '2.0.11');
AppConfig appConfig = AppConfig(version: 37, codeName: '2.0.12');

class AppConfig {
int version;
Expand Down
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:io';

import 'package:dynamic_color/dynamic_color.dart';
Expand Down
73 changes: 35 additions & 38 deletions lib/screens/home_screen/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,45 +131,42 @@ class _HomeScreenState extends State<HomeScreen> {
return AdaptiveScaffold(
appBar: PreferredSize(
preferredSize: const AdaptiveAppBar().preferredSize,
child: AdaptiveAppBar(
automaticallyImplyLeading: false,
title: Material(
color: Colors.transparent,
child: LayoutBuilder(
builder: (context, constraints) {
return Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth > 400
? (400)
: constraints.maxWidth),
child: AdaptiveTextField(
onTap: () => context.go('/search'),
readOnly: true,
keyboardType: TextInputType.text,
maxLines: 1,
autofocus: false,
textInputAction: TextInputAction.search,
fillColor: Platform.isWindows
? null
: Colors.grey.withOpacity(0.3),
contentPadding: const EdgeInsets.symmetric(
vertical: 2, horizontal: 8),
borderRadius:
BorderRadius.circular(Platform.isWindows ? 4.0 : 35),
hintText: S.of(context).Search_Gyawun,
prefix: Icon(AdaptiveIcons.search),
),
),
],
);
}
),
),
centerTitle: false,
child: AdaptiveAppBar(
automaticallyImplyLeading: false,
title: Material(
color: Colors.transparent,
child: LayoutBuilder(builder: (context, constraints) {
return Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth > 400
? (400)
: constraints.maxWidth),
child: AdaptiveTextField(
onTap: () => context.go('/search'),
readOnly: true,
keyboardType: TextInputType.text,
maxLines: 1,
autofocus: false,
textInputAction: TextInputAction.search,
fillColor: Platform.isWindows
? null
: Colors.grey.withOpacity(0.3),
contentPadding: const EdgeInsets.symmetric(
vertical: 2, horizontal: 8),
borderRadius:
BorderRadius.circular(Platform.isWindows ? 4.0 : 35),
hintText: S.of(context).Search_Gyawun,
prefix: Icon(AdaptiveIcons.search),
),
),
],
);
}),
),

centerTitle: false,
),
),
body: initialLoading
? const Center(child: AdaptiveProgressRing())
Expand Down
58 changes: 36 additions & 22 deletions lib/screens/main_screen/player_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'package:gyawun/utils/extensions.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:provider/provider.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
import 'package:text_scroll/text_scroll.dart';
Expand Down Expand Up @@ -113,9 +112,8 @@ class _PlayerScreenState extends State<PlayerScreen> {

Future<Color?> getColor(String? image, bool isDark) async {
if (image == null) return Theme.of(context).scaffoldBackgroundColor;
PaletteGenerator paletteGenerator =
await PaletteGenerator.fromImageProvider(
CachedNetworkImageProvider(
final c = await ColorScheme.fromImageProvider(
provider: CachedNetworkImageProvider(
image,
errorListener: (p0) {
if (mounted) {
Expand All @@ -128,24 +126,40 @@ class _PlayerScreenState extends State<PlayerScreen> {
},
),
);
return c.primary;
// PaletteGenerator paletteGenerator =
// await PaletteGenerator.fromImageProvider(
// CachedNetworkImageProvider(
// image,
// errorListener: (p0) {
// if (mounted) {
// setState(() {
// image = getEnhancedImage(image!,
// dp: MediaQuery.of(context).devicePixelRatio,
// quality: 'medium');
// });
// }
// },
// ),
// );

if (mounted) {
if (isDark) {
return paletteGenerator.darkVibrantColor?.color ??
paletteGenerator.dominantColor?.color ??
paletteGenerator.darkMutedColor?.color ??
paletteGenerator.lightVibrantColor?.color ??
paletteGenerator.lightMutedColor?.color;
} else {
return paletteGenerator.lightMutedColor?.color ??
paletteGenerator.darkVibrantColor?.color ??
paletteGenerator.dominantColor?.color ??
paletteGenerator.darkMutedColor?.color ??
paletteGenerator.lightVibrantColor?.color;
}
} else {
return Colors.transparent;
}
// if (mounted) {
// if (isDark) {
// return paletteGenerator.darkVibrantColor?.color ??
// paletteGenerator.dominantColor?.color ??
// paletteGenerator.darkMutedColor?.color ??
// paletteGenerator.lightVibrantColor?.color ??
// paletteGenerator.lightMutedColor?.color;
// } else {
// return paletteGenerator.lightMutedColor?.color ??
// paletteGenerator.darkVibrantColor?.color ??
// paletteGenerator.dominantColor?.color ??
// paletteGenerator.darkMutedColor?.color ??
// paletteGenerator.lightVibrantColor?.color;
// }
// } else {
// return Colors.transparent;
// }
}

MaterialColor primaryWhite = const MaterialColor(
Expand Down Expand Up @@ -675,7 +689,7 @@ class NameAndControls extends StatelessWidget {
item['status'] == 'DOWNLOADING') {
return AdaptiveProgressRing(
value: item['status'] == 'DOWNLOADING'
? item['progress']/100
? item['progress'] / 100
: null,
color: Colors.white,
backgroundColor: Colors.black,
Expand Down
126 changes: 71 additions & 55 deletions lib/services/custom_audio_stream.dart
Original file line number Diff line number Diff line change
@@ -1,55 +1,71 @@
import 'dart:async';
import 'package:gyawun/services/stream_client.dart';
import 'package:just_audio/just_audio.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';

class CustomAudioStream extends StreamAudioSource {
late YoutubeExplode ytExplode;
AudioOnlyStreamInfo? streamInfo;
String videoId;
String quality;

CustomAudioStream(this.videoId, this.quality, {super.tag}) {
ytExplode = YoutubeExplode();
}

Future _loadStreamInfo() async {
StreamManifest manifest = await ytExplode.videos.streamsClient
.getManifest(videoId, requireWatchPage: false);

List<AudioOnlyStreamInfo> streamInfos = manifest.audioOnly
.sortByBitrate()
.reversed
.where((stream) => stream.container == StreamContainer.mp4)
.toList();

int qualityIndex = quality == 'low' ? 0 : streamInfos.length - 1;
streamInfo = streamInfos[qualityIndex];
}

@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
if (streamInfo == null) {
await _loadStreamInfo();
}

start ??= 0;
int size = streamInfo!.bitrate.bitsPerSecond * 80;
end ??= (streamInfo!.isThrottled
? (start + size)
: streamInfo!.size.totalBytes);
if (end > streamInfo!.size.totalBytes) {
end = streamInfo!.size.totalBytes;
}
final response =
AudioStreamClient().getAudioStream(streamInfo, start: start, end: end);

return StreamAudioResponse(
sourceLength: streamInfo!.size.totalBytes,
contentLength: end - start,
offset: start,
stream: response,
contentType: streamInfo!.codec.type,
);
}
}
// import 'dart:async';
// import 'package:gyawun/services/stream_client.dart';
// import 'package:just_audio/just_audio.dart';
// import 'package:youtube_explode_dart/youtube_explode_dart.dart';

// mixin HlsStreamInfo on StreamInfo {
// /// The tag of the audio stream related to this stream.
// int? get audioItag => null;
// }

// class CustomAudioStream extends StreamAudioSource {
// late YoutubeExplode ytExplode;
// StreamInfo? streamInfo;
// String videoId;
// String quality;

// CustomAudioStream(this.videoId, this.quality, {super.tag}) {
// ytExplode = YoutubeExplode();
// }

// Future _loadStreamInfo() async {
// StreamManifest manifest =
// await ytExplode.videos.streamsClient.getManifest(videoId);

// List<AudioOnlyStreamInfo> streamInfos = manifest.audioOnly
// .sortByBitrate()
// .reversed
// .where((stream) => stream.container == StreamContainer.mp4)
// .toList();

// int qualityIndex = quality == 'low' ? 0 : streamInfos.length - 1;
// streamInfo = streamInfos[qualityIndex];
// if (streamInfo!.fragments.isNotEmpty) {
// print("Using DASH Fragmented Stream");
// } else if (streamInfo is HlsStreamInfo) {
// print("Using HLS Stream");
// } else {
// print("Using Normal Stream");
// }
// print(streamInfo!.url.toString());
// }

// @override
// Future<StreamAudioResponse> request([int? start, int? end]) async {
// if (streamInfo == null) {
// await _loadStreamInfo();
// }

// start ??= 0;

// int size = 10379935;
// end = start + size.clamp(0, streamInfo!.size.totalBytes - start);
// // if (!streamInfo!.isThrottled) {

// // }
// // end ??= streamInfo!.size.totalBytes;
// if (end > streamInfo!.size.totalBytes) {
// end = streamInfo!.size.totalBytes;
// }
// print('$start-$end');
// final response = ytExplode.videos.streams.get(streamInfo!, start, end);

// return StreamAudioResponse(
// sourceLength: streamInfo!.size.totalBytes,
// contentLength: null,
// offset: null,
// stream: response,
// contentType: streamInfo!.codec.type,
// );
// }
// }
35 changes: 31 additions & 4 deletions lib/services/media_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get_it/get_it.dart';
import 'package:gyawun/services/yt_audio_stream.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';

import '../utils/add_history.dart';
import '../ytmusic/ytmusic.dart';
import 'custom_audio_stream.dart';
import 'settings_manager.dart';

class MediaPlayer extends ChangeNotifier {
Expand Down Expand Up @@ -278,15 +278,42 @@ class MediaPlayer extends ChangeNotifier {
if (isDownloaded) {
audioSource = AudioSource.file(song['path'], tag: tag);
} else {
audioSource = CustomAudioStream(
song['videoId'],
GetIt.I<SettingsManager>().streamingQuality.name.toLowerCase(),
// audioSource = AudioSource.uri(
// Uri.parse(
// 'https://invidious.nerdvpn.de/latest_version?id=${song['videoId']}'),
// tag: tag,
// );

audioSource = YouTubeAudioSource(
videoId: song['videoId'],
quality: GetIt.I<SettingsManager>().streamingQuality.name.toLowerCase(),
tag: tag,
);
}
return audioSource;
}

// void download() async {
// List<String> qualVidOptions = ['480p', '720p', '1080p', '2K', '4K'];
// List<String> qualAudOptions = ['64k', '128k', '192k', '256k', '320k'];

// String command =
// 'yt-dlp -f \'bestvideo[height<=${qualVid.replaceAll('p', '')}]'
// '+bestaudio/best[height<=${qualVid.replaceAll('p', '')}]\' $ytUrl';
// if (dlAud) command += ' -x --audio-format mp3 --audio-quality ${qualAud}';
// if (dlThumb) command += ' --write-thumbnail';
// if (timeStart != null && timeEnd != null) {
// command +=
// ' --postprocessor-args "-ss ${timeStart!.format(context)} -to ${timeEnd!.format(context)}"';
// }
// Shell shell = Shell();
// if (kDebugMode) {
// print("Running command: ==================================== ");
// print(command);
// }
// await shell.run(command);
// }

Future<void> playSong(Map<String, dynamic> song,
{bool autoFetch = true}) async {
if (song['videoId'] != null) {
Expand Down
2 changes: 1 addition & 1 deletion lib/services/stream_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AudioStreamClient {
}) async* {
var url = streamInfo.url;
var bytesCount = start;
while (bytesCount != streamInfo.size.totalBytes) {
while (bytesCount != end) {
try {
final response = await retry(this, () async {
final from = bytesCount;
Expand Down
Loading

0 comments on commit 38b1e7e

Please sign in to comment.