step 11 : play and pause rekaman dan slicing edit screen
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import '../../model/edit_voice_to_text_model.dart';
|
||||
@@ -25,4 +26,12 @@ final selectedEdit = StateProvider<EditVoiceToTextModel>(
|
||||
//
|
||||
final barcodeX = StateProvider<Barcode>(
|
||||
(ref) => Barcode(),
|
||||
);
|
||||
);
|
||||
|
||||
final noteCtr = StateProvider<TextEditingController>(
|
||||
(ref) => TextEditingController(text: ""),
|
||||
);
|
||||
|
||||
final textCtr = StateProvider<TextEditingController>(
|
||||
(ref) => TextEditingController(text: ""),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:fluttervoice2text/app/route.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import '../../model/edit_voice_to_text_model.dart';
|
||||
import '../../model/voice_to_text_model.dart';
|
||||
@@ -62,9 +63,9 @@ class CardRiwayatRekaman extends HookConsumerWidget {
|
||||
Voice2text_Updated: data.Voice2text_Updated,
|
||||
Voice2text_User_ID: data.Voice2text_User_ID,
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// editRekamanRoute,
|
||||
// );
|
||||
Navigator.of(context).pushNamed(
|
||||
editRekamRoute,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
|
||||
@@ -1,13 +1,115 @@
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:toastification/toastification.dart';
|
||||
|
||||
import '../../app/constant.dart';
|
||||
import '../../provider/current_user_provider.dart';
|
||||
import '../../provider/voice_to_text_provider.dart';
|
||||
|
||||
class EditRekamScreen extends HookConsumerWidget {
|
||||
const EditRekamScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
SystemChrome.setEnabledSystemUIMode(
|
||||
SystemUiMode.manual,
|
||||
overlays: [SystemUiOverlay.bottom],
|
||||
);
|
||||
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
final host = currentUser?.host ?? "";
|
||||
final userId = currentUser?.model.userId ?? "";
|
||||
final qrCodeStr = useState("");
|
||||
final editData = ref.watch(selectedEdit);
|
||||
final baseUrl = "https://$host/";
|
||||
final player = useState(AudioPlayer());
|
||||
final urlRekaman = baseUrl + editData.Voice2text_Url;
|
||||
final isPlaying = useState(false);
|
||||
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timestamp) {
|
||||
ref.read(noteCtr.notifier).state = TextEditingController(
|
||||
text: editData.Voice2text_Note,
|
||||
);
|
||||
ref.read(textCtr.notifier).state = TextEditingController(
|
||||
text: editData.Voice2text_Text,
|
||||
);
|
||||
String afterVoice = editData.Voice2text_Url.split("voice-")[1];
|
||||
String qrCodeExtract = afterVoice.split(".mp3")[0];
|
||||
qrCodeStr.value = "Qrcode : $qrCodeExtract";
|
||||
});
|
||||
return () {};
|
||||
}, []);
|
||||
|
||||
void showLongToast(
|
||||
String title,
|
||||
String message,
|
||||
String typeToast,
|
||||
Duration waktu,
|
||||
) {
|
||||
if (typeToast == "success") {
|
||||
toastification.show(
|
||||
context: context,
|
||||
title: Text(title),
|
||||
description: Text(message),
|
||||
autoCloseDuration: waktu,
|
||||
type: ToastificationType.success,
|
||||
style: ToastificationStyle.fillColored,
|
||||
);
|
||||
} else if (typeToast == "error") {
|
||||
toastification.show(
|
||||
context: context,
|
||||
title: Text(title),
|
||||
description: Text(message),
|
||||
autoCloseDuration: waktu,
|
||||
type: ToastificationType.error,
|
||||
style: ToastificationStyle.fillColored,
|
||||
);
|
||||
} else if (typeToast == "warning") {
|
||||
toastification.show(
|
||||
context: context,
|
||||
title: Text(title),
|
||||
description: Text(message),
|
||||
autoCloseDuration: waktu,
|
||||
type: ToastificationType.warning,
|
||||
style: ToastificationStyle.fillColored,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> playRekaman() async {
|
||||
if (urlRekaman.isNotEmpty) {
|
||||
try {
|
||||
if (isPlaying.value) {
|
||||
await player.value.pause(); // Pause jika sedang diputar
|
||||
} else {
|
||||
await player.value.setSourceUrl(urlRekaman);
|
||||
await player.value.resume(); // Putar jika tidak sedang diputar
|
||||
}
|
||||
isPlaying.value = !isPlaying.value;
|
||||
} catch (e) {
|
||||
print("Error saat memutar rekaman: ${e.toString()}");
|
||||
showLongToast(
|
||||
'Error',
|
||||
"Error saat memutar rekaman: ${e.toString()}",
|
||||
'error',
|
||||
Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
print("URL rekaman kosong");
|
||||
showLongToast(
|
||||
'Error',
|
||||
"URL rekaman kosong",
|
||||
'error',
|
||||
Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
FocusManager.instance.primaryFocus!.unfocus();
|
||||
@@ -15,6 +117,56 @@ class EditRekamScreen extends HookConsumerWidget {
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
backgroundColor: Constant.bgGrey,
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
color: Colors.blueGrey.shade100,
|
||||
height: Constant.getActualYPhone(context: context, y: 100),
|
||||
shape: const CircularNotchedRectangle(),
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon:
|
||||
Icon(Icons.arrow_back, size: 17, color: Constant.textWhite),
|
||||
label: Text(
|
||||
'Kembali',
|
||||
style: Constant.cardText(context: context)
|
||||
.copyWith(color: Constant.textWhite),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Constant.textBlack,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 8,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
onPressed: playRekaman,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Constant.bgButton,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'SAVE',
|
||||
style: Constant.titleButton500(context: context).copyWith(
|
||||
color: Constant.textWhite,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// atas
|
||||
@@ -23,6 +175,125 @@ class EditRekamScreen extends HookConsumerWidget {
|
||||
width: double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 50,
|
||||
),
|
||||
),
|
||||
// qrcode
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
color: Constant.inputanGrey,
|
||||
child: Text(
|
||||
qrCodeStr.value,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 20,
|
||||
),
|
||||
),
|
||||
// button play record
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: playRekaman,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Constant.textRed,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 8,
|
||||
shadowColor: Constant.bgButton.withOpacity(0.24),
|
||||
),
|
||||
child: Text(
|
||||
isPlaying.value ? 'STOP' : 'PUTAR REKAMAN',
|
||||
style: Constant.titleButton500(context: context).copyWith(
|
||||
color: Constant.textWhite,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 20,
|
||||
),
|
||||
),
|
||||
// note
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
child: TextField(
|
||||
controller: ref.read(noteCtr),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
decoration: InputDecoration(
|
||||
label: Text('Note'),
|
||||
hintText: "Note",
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.blue,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 20,
|
||||
),
|
||||
),
|
||||
// hasil transcribe
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
child: TextField(
|
||||
controller: ref.read(textCtr),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
decoration: InputDecoration(
|
||||
label: Text('Text'),
|
||||
hintText: "Text",
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.blue,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -84,78 +84,6 @@ class RekamScreen extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> jalankanRekaman() async {
|
||||
try {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final filePath = '${dir.path}/myFile.aac';
|
||||
// final filePath = '${dir.path}/myFile.mp3';
|
||||
audioPath.value = filePath;
|
||||
|
||||
await recorder.value.startRecorder(
|
||||
toFile: filePath,
|
||||
);
|
||||
|
||||
judulTombol.value = "SELESAI";
|
||||
isSelesaiRekam.value = true;
|
||||
} catch (e) {
|
||||
print("Error start record ${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> convertToMp3(String inputPath) async {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final outputPath = "${dir.path}/output.mp3";
|
||||
|
||||
// Jalankan perintah FFmpeg untuk konversi
|
||||
await FFmpegKit.execute(
|
||||
'-i $inputPath -codec:a libmp3lame -qscale:a 2 $outputPath');
|
||||
|
||||
// Pastikan file MP3 berhasil dibuat
|
||||
if (File(outputPath).existsSync()) {
|
||||
return outputPath;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> playRecording() async {
|
||||
try {
|
||||
if (audioPath.value.isNotEmpty && File(audioPath.value).existsSync()) {
|
||||
await player.value.startPlayer(fromURI: audioPath.value);
|
||||
} else {
|
||||
print("Error: Path rekaman kosong atau tidak ditemukan.");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error saat memutar rekaman: ${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> berhentiRekaman() async {
|
||||
try {
|
||||
await recorder.value.stopRecorder();
|
||||
isSelesaiRekam.value = false;
|
||||
|
||||
// panggil fungsi untuk kirim ke BE
|
||||
if (audioPath.value.isNotEmpty) {
|
||||
String? mp3Path = await convertToMp3(audioPath.value);
|
||||
if (mp3Path != null) {
|
||||
// await uploadAudioFile(mp3Path);
|
||||
ref.read(uploadRekamProvider.notifier).uploadRekam(
|
||||
host: host,
|
||||
filePath: mp3Path,
|
||||
userId: userId,
|
||||
qrCodeStr: qrCodeStr.value,
|
||||
);
|
||||
print('mp3 convert $mp3Path');
|
||||
} else {
|
||||
print("Konversi gagal!");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error stop record ${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
void showLongToast(
|
||||
String title,
|
||||
String message,
|
||||
@@ -192,6 +120,83 @@ class RekamScreen extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> jalankanRekaman() async {
|
||||
try {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final filePath = '${dir.path}/myFile.aac';
|
||||
// final filePath = '${dir.path}/myFile.mp3';
|
||||
audioPath.value = filePath;
|
||||
|
||||
await recorder.value.startRecorder(
|
||||
toFile: filePath,
|
||||
);
|
||||
|
||||
judulTombol.value = "SELESAI";
|
||||
isSelesaiRekam.value = true;
|
||||
} catch (e) {
|
||||
print("Error start record ${e.toString()}");
|
||||
showLongToast(
|
||||
'Error',
|
||||
"Error start record ${e.toString()}",
|
||||
'error',
|
||||
Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> convertToMp3(String inputPath) async {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final outputPath = "${dir.path}/output.mp3";
|
||||
|
||||
// Jalankan perintah FFmpeg untuk konversi
|
||||
await FFmpegKit.execute(
|
||||
'-i $inputPath -codec:a libmp3lame -qscale:a 2 $outputPath');
|
||||
|
||||
// Pastikan file MP3 berhasil dibuat
|
||||
if (File(outputPath).existsSync()) {
|
||||
return outputPath;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> berhentiRekaman() async {
|
||||
try {
|
||||
await recorder.value.stopRecorder();
|
||||
isSelesaiRekam.value = false;
|
||||
|
||||
// panggil fungsi untuk kirim ke BE
|
||||
if (audioPath.value.isNotEmpty) {
|
||||
String? mp3Path = await convertToMp3(audioPath.value);
|
||||
if (mp3Path != null) {
|
||||
// await uploadAudioFile(mp3Path);
|
||||
ref.read(uploadRekamProvider.notifier).uploadRekam(
|
||||
host: host,
|
||||
filePath: mp3Path,
|
||||
userId: userId,
|
||||
qrCodeStr: qrCodeStr.value,
|
||||
);
|
||||
} else {
|
||||
print("Konversi gagal!");
|
||||
showLongToast(
|
||||
'Error',
|
||||
"Konversi gagal!",
|
||||
'error',
|
||||
Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error stop record ${e.toString()}");
|
||||
showLongToast(
|
||||
'Error',
|
||||
"Error stop record ${e.toString()}",
|
||||
'error',
|
||||
Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// list Riwayat Rekam
|
||||
ref.listen(listRiwayatRekamanProvider, (prev, next) {
|
||||
if (next is ListRiwayatRekamanStateLoading) {
|
||||
@@ -307,7 +312,7 @@ class RekamScreen extends HookConsumerWidget {
|
||||
.copyWith(color: Constant.textWhite),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green.shade400,
|
||||
backgroundColor: Constant.textBlack,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
@@ -370,7 +375,7 @@ class RekamScreen extends HookConsumerWidget {
|
||||
padding: EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Column(
|
||||
children: [
|
||||
if (awalan.value == "Info :")
|
||||
if (awalan.value == "Info :")
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: Constant.getActualYPhone(
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
|
||||
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import audioplayers_darwin
|
||||
import ffmpeg_kit_flutter_audio
|
||||
import mobile_scanner
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
||||
FFmpegKitFlutterPlugin.register(with: registry.registrar(forPlugin: "FFmpegKitFlutterPlugin"))
|
||||
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
|
||||
64
pubspec.lock
64
pubspec.lock
@@ -9,6 +9,62 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
audioplayers:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: audioplayers
|
||||
sha256: b3d02a23918b980073d4a76c4e5659eaf5127251ca91a6a804869ba88ef1c8bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
audioplayers_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_android
|
||||
sha256: "56830454da1a943f33c686cdbfca52a8d24f4c6fd6ce88c6b3501020dbaaf48b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.3"
|
||||
audioplayers_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_darwin
|
||||
sha256: "34e1fb3a88ba02566615c6ca7173aa93b39cf61a38a05a729b60ba14c4899169"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
audioplayers_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_linux
|
||||
sha256: ce8383c1ff0db1ba93b5b0b8ef5b260ec2d0ce2598ad37dc8b946b773dd2c5fa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
audioplayers_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_platform_interface
|
||||
sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
audioplayers_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_web
|
||||
sha256: "3609bdf0e05e66a3d9750ee40b1e37f2a622c4edb796cc600b53a90a30a2ace4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
audioplayers_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audioplayers_windows
|
||||
sha256: "52b57c706a20fc85daa911be67381b3a5c9d03f8e27cb9fdb226de5bddf293b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -216,6 +272,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -50,6 +50,7 @@ dependencies:
|
||||
mobile_scanner: ^6.0.6
|
||||
flutter_sound: ^9.23.1
|
||||
ffmpeg_kit_flutter_audio: ^6.0.3
|
||||
audioplayers: ^6.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AudioplayersWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_windows
|
||||
permission_handler_windows
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user