Skip to content

Commit

Permalink
Merge branch 'master' of github.com:HeHang0/musiche
Browse files Browse the repository at this point in the history
  • Loading branch information
HeHang0 committed Mar 20, 2024
2 parents 2e5a653 + 7b17b2a commit 9fe7454
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 35 deletions.
25 changes: 13 additions & 12 deletions mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
PODS:
- audio_service (0.0.1):
- Flutter
- audio_session (0.0.1):
- Flutter
- device_info_plus (0.0.1):
Expand Down Expand Up @@ -59,15 +61,15 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.4)
- url_launcher_ios (0.0.1):
- Flutter
- webf (0.14.0):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter

DEPENDENCIES:
- audio_service (from `.symlinks/plugins/audio_service/ios`)
- audio_session (from `.symlinks/plugins/audio_session/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
Expand All @@ -77,9 +79,8 @@ DEPENDENCIES:
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webf (from `.symlinks/plugins/webf/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)

SPEC REPOS:
trunk:
Expand All @@ -90,6 +91,8 @@ SPEC REPOS:
- SwiftyGif

EXTERNAL SOURCES:
audio_service:
:path: ".symlinks/plugins/audio_service/ios"
audio_session:
:path: ".symlinks/plugins/audio_session/ios"
device_info_plus:
Expand All @@ -108,14 +111,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
webf:
:path: ".symlinks/plugins/webf/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"

SPEC CHECKSUMS:
audio_service: f509d65da41b9521a61f1c404dd58651f265a567
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
Expand All @@ -129,10 +131,9 @@ SPEC CHECKSUMS:
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
SDWebImage: 981fd7e860af070920f249fd092420006014c3eb
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
webf: 904888515f25428e7f769866541e3c453da9cbee
webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36

PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

Expand Down
4 changes: 4 additions & 0 deletions mobile/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,9 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
</dict>
</plist>
88 changes: 76 additions & 12 deletions mobile/lib/audio/audio_play.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'dart:async';
import 'dart:io';

import 'package:audio_service/audio_service.dart';
import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart';
import 'package:musiche/utils/android_channel.dart';

import 'media_metadata.dart';

class AudioPlay {
class AudioPlay extends BaseAudioHandler {
late final AudioPlayer _audioPlayer;
Stream<PlayerState> get onPlayerStateChanged => _audioPlayer.playerStateStream;
Stream<Duration?> get onDurationChanged => _audioPlayer.durationStream;
Expand All @@ -18,44 +19,107 @@ class AudioPlay {
Future<Duration?> Function() get currentPosition => () => Future(() => _audioPlayer.position);
Future<Duration?> Function() get duration => () => Future(() => _audioPlayer.duration);
MediaMetadata? metadata;

AudioPlay(){
_audioPlayer = AudioPlayer();
_initAudioService();
onDurationChanged.listen(_onDurationChanged);
onPositionChanged.listen(_onPositionChanged);
onPlayerStateChanged.listen(_onPlayerStateChanged);
}
Future<void> _initAudioService() async {
await AudioService.init(
builder: () => this,
config: const AudioServiceConfig(
androidNotificationChannelId: 'com.picapico.musiche.channel.audio',
androidNotificationChannelName: 'Musiche playback',
),
);
}

@override
Future<void> play() async {
playCurrent();
}
// @override
// Future<void> pause() async {}
@override
Future<void> stop() async {
pause();
}
@override
Future<void> seek(Duration position) async {
_audioPlayer.seek(position);
}
@override
Future<void> skipToNext() async {}
@override
Future<void> skipToPrevious() async {}
// @override
// Future<void> skipToQueueItem(int i) async {}

_onPlayerStateChanged(PlayerState state) async {
if(metadata == null) return;
setMediaMeta(metadata!);
setMediaMeta(metadata);
}

Future<void> _onPositionChanged(Duration position) async {
if(kIsWeb) return;
if(Platform.isAndroid) AndroidChannel.setMediaPosition(playing, position.inMilliseconds);
if(Platform.isAndroid) {
AndroidChannel.setMediaPosition(playing, position.inMilliseconds);
} else{
playbackState?.add(PlaybackState(
controls: [
MediaControl.skipToPrevious,
playing ? MediaControl.pause : MediaControl.play,
MediaControl.skipToNext,
],
systemActions: const {
MediaAction.seek
},
androidCompactActionIndices: const [0, 1, 2],
processingState: AudioProcessingState.ready,
playing: _audioPlayer.playing,
updatePosition: _audioPlayer.position,
bufferedPosition: _audioPlayer.bufferedPosition,
speed: 1.0,
queueIndex: 0,
));
}
}

Future<void> _onDurationChanged(Duration? duration) async {
if(metadata == null || _audioPlayer.duration == null) return;
if(kIsWeb) return;
if(Platform.isAndroid) AndroidChannel.setMediaMetadata(metadata!, playing, _audioPlayer.position.inMilliseconds, _audioPlayer.duration!.inMilliseconds);
setMediaMeta(metadata);
}

Future<void> setMediaMeta(MediaMetadata metadata) async {
Future<void> setMediaMeta(MediaMetadata? metadata) async {
if(metadata == null) return;
this.metadata = metadata;
Duration? duration = _audioPlayer.duration;
if(duration == null || duration.inMilliseconds == 0){
return;
}
if(kIsWeb) return;
if(Platform.isAndroid) AndroidChannel.setMediaMetadata(metadata, playing, _audioPlayer.position.inMilliseconds, duration.inMilliseconds);
if(Platform.isAndroid) {
AndroidChannel.setMediaMetadata(metadata, playing, _audioPlayer.position.inMilliseconds, duration.inMilliseconds);
} else {
var item = MediaItem(
id: metadata.title + metadata.artist,
title: metadata.title,
album: metadata.album,
artist: metadata.album,
duration: duration,
artUri: Uri.parse(metadata.artwork)
);
mediaItem?.add(item);
playMediaItem(item);
}
}
void pause() {

@override
Future<void> pause() async {
_audioPlayer.pause();
}

Future<void> play(String url) async {
Future<void> playUrl(String url) async {
if(url.isEmpty) {
playCurrent();
return;
Expand Down
2 changes: 1 addition & 1 deletion mobile/lib/server/http_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class HttpHandler extends Handler implements IHandler {
}

Future<void> _play(HttpRequest request) async {
await audioPlay.play(await _readBody(request));
await audioPlay.playUrl(await _readBody(request));
await _sendStatus(request);
}

Expand Down
6 changes: 5 additions & 1 deletion mobile/lib/webview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class WebViewApp extends StatefulWidget {
class _WebViewAppState extends State<WebViewApp> with WidgetsBindingObserver {
static const String _tag = "MusicWebView";
final GlobalKey webViewKey = GlobalKey();
static final String _url = kDebugMode ? "http://192.168.3.2:5173" : "http://127.0.0.1:${ServerManager.port}/index.html";
static final String _url = kDebugMode ? "http://192.168.3.165:5173" : "http://127.0.0.1:${ServerManager.port}/index.html";
InAppWebViewController? webViewController;
InAppWebViewSettings settings = InAppWebViewSettings(
isInspectable: kDebugMode,
Expand Down Expand Up @@ -143,6 +143,9 @@ class _WebViewAppState extends State<WebViewApp> with WidgetsBindingObserver {
resources: request.resources,
action: PermissionResponseAction.GRANT);
}
Future<ServerTrustAuthResponse?> _onReceivedServerTrustAuthRequest(controller, challenge){
return Future(() => null);
}
_onReceivedError(controller, request, error) {
Logger.e(_tag, "receive web error", error: error);
}
Expand Down Expand Up @@ -180,6 +183,7 @@ class _WebViewAppState extends State<WebViewApp> with WidgetsBindingObserver {
onProgressChanged: _onProgressChanged,
onConsoleMessage: _onConsoleMessage,
onPermissionRequest: _onPermissionRequest,
onReceivedServerTrustAuthRequest: _onReceivedServerTrustAuthRequest
),
)
);
Expand Down
4 changes: 4 additions & 0 deletions mobile/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import FlutterMacOS
import Foundation

import audio_service
import audio_session
import device_info_plus
import flutter_inappwebview_macos
import just_audio
import path_provider_foundation
import shared_preferences_foundation
import sqflite
import url_launcher_macos

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
1 change: 1 addition & 0 deletions mobile/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies:

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
audio_service: ^0.18.12
cupertino_icons: ^1.0.2
device_info_plus: ^9.1.1
file_picker: ^6.1.1
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const play = usePlayStore();
</template>
</el-popover>
<el-popover
v-if="play.remoteMode"
v-if="!isMobile"
placement="top"
:width="30"
popper-class="music-footer-volume-popover"
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/SideMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function toHome() {
getServiceWorkerRegistration()?.update();
push('/');
}
const canDirectoryPicker = Boolean((window as any).showDirectoryPicker);
</script>

<template>
Expand Down Expand Up @@ -63,7 +64,7 @@ function toHome() {
setting.userInfo.qq.id ||
setting.userInfo.migu.id
)
: item.key !== 'local' || !play.remoteMode
: true
"
:class="route.meta.key == item.key ? 'is-active' : ''">
<span class="music-icon">{{ item.icon }}</span>
Expand All @@ -73,7 +74,7 @@ function toHome() {
<el-menu-item
index="/local"
id="/local"
v-if="setting.config.file || Boolean((window as any).showDirectoryPicker)"
v-if="setting.config.file || canDirectoryPicker"
:class="route.meta.key == 'local' ? 'is-active' : ''">
<span class="music-icon">乐</span>
<span>本地音乐</span>
Expand Down
2 changes: 1 addition & 1 deletion web/src/stores/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ export const usePlayStore = defineStore('play', {
} else {
title.value = '音乐和';
}
if (this.config.remote) return;
if (this.config.list) return;
musicOperate('/title', title.value);
musicOperate(
'/media',
Expand Down
2 changes: 1 addition & 1 deletion web/src/utils/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const musicRouterPrefix = localStorage.getItem('musiche-router-prefix');
const history = musicRouterPrefix ? '/' + musicRouterPrefix : '';

export const httpAddress = import.meta.env.DEV
? '192.168.3.194:8090'
? '127.0.0.1:54621'
: location.host;
let proxyAddress =
localStorage.getItem('musiche-proxy-address') || `//${httpAddress}/proxy`;
Expand Down
12 changes: 8 additions & 4 deletions web/src/views/setting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -660,19 +660,19 @@ onUnmounted(unWatch);
<td></td>
<td class="music-setting-play">
<el-checkbox
v-if="!setting.remoteMode"
v-if="setting.config.file"
v-model="setting.pageValue.playAtRun"
@change="setting.setPlayAtRun"
label="程序启动时自动播放"
size="large" />
<el-checkbox
v-if="!setting.remoteMode"
v-if="setting.config.file"
v-model="setting.pageValue.savePlayProgress"
@change="setting.setSavePlayProgress"
label="程序启动时记住上一次播放进度"
size="large" />
<el-checkbox
v-if="!setting.remoteMode"
v-if="setting.config.file"
v-model="setting.pageValue.fadeIn"
@change="setting.setFadeIn()"
label="开启音乐淡入"
Expand Down Expand Up @@ -936,7 +936,11 @@ onUnmounted(unWatch);
<td></td>
<td class="music-setting-about">
<span> 当前版本 {{ currentVersion }} </span>
<span v-if="!setting.remoteMode && currentVersion != remoteVersion">
<span
v-if="
(!setting.config.remote || setting.config.file) &&
currentVersion != remoteVersion
">
最新版本 {{ remoteVersion }}
</span>
<span
Expand Down

0 comments on commit 9fe7454

Please sign in to comment.