From 0dd071ef405c86f40dee215a2f05a59e7ca74a35 Mon Sep 17 00:00:00 2001 From: Brian Tu Date: Thu, 2 Nov 2023 09:43:48 -0700 Subject: [PATCH] Added homepage --- android/app/build.gradle | 6 +- lib/home.dart | 261 +++++++++++++++++++++++++++++++++++++++ lib/main.dart | 197 +++++++++++++++-------------- pubspec.lock | 16 +++ pubspec.yaml | 2 + 5 files changed, 387 insertions(+), 95 deletions(-) create mode 100644 lib/home.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 111db75..986b4b3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -25,7 +25,7 @@ if (flutterVersionName == null) { android { namespace "com.example.flutter_noise_apps_117" compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion + ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -45,10 +45,10 @@ android { applicationId "com.example.flutter_noise_apps_117" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 24 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + versionName flutterVersionName } buildTypes { diff --git a/lib/home.dart b/lib/home.dart new file mode 100644 index 0000000..86d9624 --- /dev/null +++ b/lib/home.dart @@ -0,0 +1,261 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_picker/flutter_picker.dart'; +import 'package:quiver/async.dart'; + + + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + // HomePage({Key key, this.title}) : super(key: key); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State with TickerProviderStateMixin { + late AnimationController _controller; + int userDuration = 0; + Duration userInterval = Duration(seconds: 1); + Duration currDuration = Duration(seconds: 0); + int counter = 0; + late StreamSubscription timer; + + void onTapDuration() { + Picker( + adapter: NumberPickerAdapter(data: [ + const NumberPickerColumn(begin: 0, end: 999, suffix: Text(' hours')), + const NumberPickerColumn(begin: 0, end: 60, suffix: Text(' minutes')), + const NumberPickerColumn(begin: 0, end: 60, suffix: Text(' seconds')) + ]), + delimiter: [ + PickerDelimiter( + child: Container( + width: 30.0, + alignment: Alignment.center, + child: Icon(Icons.more_vert), + ), + ) + ], + hideHeader: true, + confirmText: 'OK', + confirmTextStyle: TextStyle(inherit: false, color: Colors.red, fontSize: 22), + title: const Text('Select Duration'), + selectedTextStyle: TextStyle(color: Colors.blue), + onConfirm: (Picker picker, List value) { + // You get your duration here + setState(() { + userDuration = Duration(hours: picker.getSelectedValues()[0], minutes: picker.getSelectedValues()[1], seconds: picker.getSelectedValues()[2]).inSeconds; + currDuration = Duration(seconds: userDuration); + print(currDuration); + }); + }, + ).showDialog(context); + } + + void onTapInterval() { + Picker( + adapter: NumberPickerAdapter(data: [ + const NumberPickerColumn(begin: 0, end: 999, suffix: Text(' hours')), + const NumberPickerColumn(begin: 0, end: 60, suffix: Text(' minutes')), + const NumberPickerColumn(begin: 0, end: 60, suffix: Text(' seconds')) + ]), + delimiter: [ + PickerDelimiter( + child: Container( + width: 50.0, + alignment: Alignment.center, + child: Icon(Icons.more_vert), + ), + ) + ], + hideHeader: true, + confirmText: 'OK', + confirmTextStyle: TextStyle(inherit: false, color: Colors.red, fontSize: 22), + title: const Text('Select Interval'), + selectedTextStyle: TextStyle(color: Colors.blue), + onConfirm: (Picker picker, List value) { + // You get your duration here + setState(() { + userInterval = Duration(hours: picker.getSelectedValues()[0], minutes: picker.getSelectedValues()[1], seconds: picker.getSelectedValues()[2]); + print(userInterval); + + }); + + }, + ).showDialog(context); + } + + + + + + // void _incrementCounter() { + // setState(() { + // _counter++; + // }); + // } + + // @override + // void dispose() { + // _controller.dispose(); + // super.dispose(); + // } + + // @override + // void initState() { + // super.initState(); + + // _controller = AnimationController( + // vsync: this, + // duration: Duration( + // seconds: + // userDuration) // duration is a user entered number elsewhere in the applciation + // ); + + + // } + + + + void startTimer() { + CountdownTimer countDownTimer = CountdownTimer( + new Duration(seconds: userDuration), + new Duration(seconds: 1), + ); + + timer = countDownTimer.listen(null); + timer.onData((duration) { + int secondsElapsed = duration.elapsed.inSeconds as int; + + setState(() { + currDuration = Duration(seconds: userDuration - secondsElapsed); + + }); + counter++; + + if (counter == userInterval.inSeconds) + { + print("DO SOME CRAZY MATH"); + counter = 0; + } + }); + + timer.onDone(() { + print("Done"); + counter = 0; + timer.cancel(); + }); + } + + void stopTimer() { + print("Canceling Timer!"); + setState(() { + userDuration = 0; + currDuration = Duration(seconds: userDuration); + print(currDuration); + }); + timer.cancel(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Noise App"), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + style: TextStyle( + fontSize: 40, + color: Theme.of(context).primaryColor, + ), + 'DURATION:' + ), + Text( + style: TextStyle( + fontSize: 40, + color: Theme.of(context).primaryColor, + ), + '${currDuration.inHours.remainder(60).toString().padLeft(2, '0')}:${currDuration.inMinutes.remainder(60).toString().padLeft(2, '0')}:${currDuration.inSeconds.remainder(60).toString().padLeft(2, '0')}' + ), + ElevatedButton( + onPressed: onTapDuration, + child: Text("Set Duration")), + Text( + style: TextStyle( + fontSize: 40, + color: Theme.of(context).primaryColor, + ), + 'INTERVAL:' + ), + Text( + style: TextStyle( + fontSize: 40, + color: Theme.of(context).primaryColor, + ), + '${userInterval.inHours.remainder(60).toString().padLeft(2, '0')}:${userInterval.inMinutes.remainder(60).toString().padLeft(2, '0')}:${userInterval.inSeconds.remainder(60).toString().padLeft(2, '0')}' + ), + // Countdown( + // animation: StepTween( + // begin: userDuration, // THIS IS A USER ENTERED NUMBER + // end: 0, + // ).animate(_controller), + // interval: 10, + // startTimeInSeconds: userDuration, + // ), + + ElevatedButton( + onPressed: onTapInterval, + child: Text("Set Interval")), + ElevatedButton( + onPressed: () => {startTimer()}, + child: Text("Start")), + ElevatedButton( + onPressed: () => {stopTimer()}, + child: Text("Cancel")) + ], + ), + ), + ); + } +} + +// class Countdown extends AnimatedWidget { +// Countdown({super.key, required this.animation, required this.interval, required this.startTimeInSeconds}) : super(listenable: animation); +// Animation animation; +// int interval; +// int startTimeInSeconds; +// @override +// build(BuildContext context) { +// Duration clockTimer = Duration(seconds: animation.value); + +// String timerText = +// '${clockTimer.inHours.remainder(60).toString().padLeft(2, '0')}:${clockTimer.inMinutes.remainder(60).toString().padLeft(2, '0')}:${clockTimer.inSeconds.remainder(60).toString().padLeft(2, '0')}'; + +// // print('startTimeInSeconds ${startTimeInSeconds}'); +// // print('interval ${interval}'); +// print('animation.value ${animation.value} '); +// // print('inMinutes ${clockTimer.inMinutes.toString()}'); +// // print('inSeconds ${clockTimer.inSeconds.toString()}'); +// // print('inSeconds.remainder ${clockTimer.inSeconds.remainder(60).toString()}'); + +// if ((startTimeInSeconds - animation.value) % interval == 0) +// { +// print("INTERVAL MET"); +// } + +// return Text( +// "$timerText", +// style: TextStyle( +// fontSize: 60, +// color: Theme.of(context).primaryColor, +// ), +// ); +// } +// } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c34af67..ebb0028 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,100 +4,113 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:audio_streamer/audio_streamer.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'home.dart'; -void main() => runApp(new AudioStreamingApp()); +void main() => runApp(MyApp()); -class AudioStreamingApp extends StatefulWidget { - @override - AudioStreamingAppState createState() => new AudioStreamingAppState(); -} - -class AudioStreamingAppState extends State { - int? sampleRate; - bool isRecording = false; - List audio = []; - List? latestBuffer; - double? recordingTime; - StreamSubscription>? audioSubscription; - - /// Check if microphone permission is granted. - Future checkPermission() async => await Permission.microphone.isGranted; - - /// Request the microphone permission. - Future requestPermission() async => - await Permission.microphone.request(); - - /// Call-back on audio sample. - void onAudio(List buffer) async { - audio.addAll(buffer); - - // Get the actual sampling rate, if not already known. - sampleRate ??= await AudioStreamer().actualSampleRate; - recordingTime = audio.length / sampleRate!; - print(audio); - - setState(() => latestBuffer = buffer); - } - - /// Call-back on error. - void handleError(Object error) { - setState(() => isRecording = false); - print(error); - } - - /// Start audio sampling. - void start() async { - // Check permission to use the microphone. - // - // Remember to update the AndroidManifest file (Android) and the - // Info.plist and pod files (iOS). - if (!(await checkPermission())) { - await requestPermission(); - } - - // Set the sampling rate - works only on Android. - AudioStreamer().sampleRate = 44100; - - // Start listening to the audio stream. - audioSubscription = - AudioStreamer().audioStream.listen(onAudio, onError: handleError); - - setState(() => isRecording = true); - } - - /// Stop audio sampling. - void stop() async { - audioSubscription?.cancel(); - setState(() => isRecording = false); - } +class MyApp extends StatelessWidget { + const MyApp({super.key}); @override - Widget build(BuildContext context) => MaterialApp( - home: Scaffold( - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: EdgeInsets.all(25), - child: Column(children: [ - Container( - child: Text(isRecording ? "Mic: ON" : "Mic: OFF", - style: TextStyle(fontSize: 25, color: Colors.blue)), - margin: EdgeInsets.only(top: 20), - ), - Text(''), - Text('Max amp: ${latestBuffer?.reduce(max)}'), - Text('Min amp: ${latestBuffer?.reduce(min)}'), - Text( - '${recordingTime?.toStringAsFixed(2)} seconds recorded.'), - ])), - ])), - floatingActionButton: FloatingActionButton( - backgroundColor: isRecording ? Colors.red : Colors.green, - child: isRecording ? Icon(Icons.stop) : Icon(Icons.mic), - onPressed: isRecording ? stop : start, - ), - ), - ); + Widget build(BuildContext context) { + return MaterialApp( + title: 'Demo', + home: HomePage(), + ); + } } + +// class AudioStreamingApp extends StatefulWidget { +// @override +// AudioStreamingAppState createState() => new AudioStreamingAppState(); +// } + +// class AudioStreamingAppState extends State { +// int? sampleRate; +// bool isRecording = false; +// List audio = []; +// List? latestBuffer; +// double? recordingTime; +// StreamSubscription>? audioSubscription; + +// /// Check if microphone permission is granted. +// Future checkPermission() async => await Permission.microphone.isGranted; + +// /// Request the microphone permission. +// Future requestPermission() async => +// await Permission.microphone.request(); + +// /// Call-back on audio sample. +// void onAudio(List buffer) async { +// audio.addAll(buffer); + +// // Get the actual sampling rate, if not already known. +// sampleRate ??= await AudioStreamer().actualSampleRate; +// recordingTime = audio.length / sampleRate!; +// print(audio); + +// setState(() => latestBuffer = buffer); +// } + +// /// Call-back on error. +// void handleError(Object error) { +// setState(() => isRecording = false); +// print(error); +// } + +// /// Start audio sampling. +// void start() async { +// // Check permission to use the microphone. +// // +// // Remember to update the AndroidManifest file (Android) and the +// // Info.plist and pod files (iOS). +// if (!(await checkPermission())) { +// await requestPermission(); +// } + +// // Set the sampling rate - works only on Android. +// AudioStreamer().sampleRate = 44100; + +// // Start listening to the audio stream. +// audioSubscription = +// AudioStreamer().audioStream.listen(onAudio, onError: handleError); + +// setState(() => isRecording = true); +// } + +// /// Stop audio sampling. +// void stop() async { +// audioSubscription?.cancel(); +// setState(() => isRecording = false); +// } + +// @override +// Widget build(BuildContext context) => MaterialApp( +// home: Scaffold( +// body: Center( +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Container( +// margin: EdgeInsets.all(25), +// child: Column(children: [ +// Container( +// child: Text(isRecording ? "Mic: ON" : "Mic: OFF", +// style: TextStyle(fontSize: 25, color: Colors.blue)), +// margin: EdgeInsets.only(top: 20), +// ), +// Text(''), +// Text('Max amp: ${latestBuffer?.reduce(max)}'), +// Text('Min amp: ${latestBuffer?.reduce(min)}'), +// Text( +// '${recordingTime?.toStringAsFixed(2)} seconds recorded.'), +// ])), +// ])), +// floatingActionButton: FloatingActionButton( +// backgroundColor: isRecording ? Colors.red : Colors.green, +// child: isRecording ? Icon(Icons.stop) : Icon(Icons.mic), +// onPressed: isRecording ? stop : start, +// ), +// ), +// ); +// } diff --git a/pubspec.lock b/pubspec.lock index 11516c1..bfac305 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -182,6 +182,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_picker: + dependency: "direct main" + description: + name: flutter_picker + sha256: "2f94c6eefba8697b07e3cd008b75f06b4ba7053cb26d23ae0fcd5932b7dc75af" + url: "https://pub.dev" + source: hosted + version: "2.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -432,6 +440,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.6" + quiver: + dependency: "direct main" + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" record: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 0637234..ec35cba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,8 @@ dependencies: just_audio: ^0.9.35 microphone: ^0.1.0 mp_audio_stream: ^0.1.4 + flutter_picker: ^2.1.0 + quiver: ^3.2.1 dev_dependencies: flutter_test: