jc_audio_controller.dart 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2022, the Flutter project authors. Please see the AUTHORS file
  2. // for details. All rights reserved. Use of this source code is governed by a
  3. // BSD-style license that can be found in the LICENSE file.
  4. import 'package:flutter/widgets.dart';
  5. import 'package:logging/logging.dart';
  6. import 'package:puzzleweave/settings/settings_controller.dart';
  7. import 'package:jc_audio_player/jc_audio_player.dart';
  8. enum SfxType { drop, click, tap, kick, pop, appear, alert, star, success, flip, card, cardShort, panstart, panend, panend2 }
  9. //AudioLogger.logLevel = AudioLogLevel.info;
  10. /// Allows playing music and sound. A facade to `package:audioplayers`.
  11. class JcAudioController {
  12. static final _log = Logger('JcAudioController');
  13. SettingsController? _settings;
  14. ValueNotifier<AppLifecycleState>? _lifecycleNotifier;
  15. final JcAudioPlayer _audioPlayer = JcAudioPlayer();
  16. JcAudioController() {
  17. _audioPlayer.addMusic(1, 'assets/audio/bgm/canon.mp3');
  18. _audioPlayer.addSound(SfxType.drop.index, 'assets/audio/sfx/button_click8.mp3');
  19. _audioPlayer.addSound(SfxType.click.index, 'assets/audio/sfx/click.mp3');
  20. _audioPlayer.addSound(SfxType.tap.index, 'assets/audio/sfx/tap.mp3');
  21. _audioPlayer.addSound(SfxType.pop.index, 'assets/audio/sfx/pop.mp3');
  22. _audioPlayer.addSound(SfxType.appear.index, 'assets/audio/sfx/appear.mp3');
  23. _audioPlayer.addSound(SfxType.alert.index, 'assets/audio/sfx/alert.mp3');
  24. _audioPlayer.addSound(SfxType.star.index, 'assets/audio/sfx/star.mp3');
  25. _audioPlayer.addSound(SfxType.success.index, 'assets/audio/sfx/success3.mp3');
  26. _audioPlayer.addSound(SfxType.card.index, 'assets/audio/sfx/card.mp3');
  27. _audioPlayer.addSound(SfxType.cardShort.index, 'assets/audio/sfx/card2.mp3');
  28. _audioPlayer.addSound(SfxType.flip.index, 'assets/audio/sfx/flip.mp3');
  29. _audioPlayer.addSound(SfxType.panstart.index, 'assets/audio/sfx/pan_start.mp3');
  30. _audioPlayer.addSound(SfxType.panend.index, 'assets/audio/sfx/pan_end.mp3');
  31. _audioPlayer.addSound(SfxType.panend2.index, 'assets/audio/sfx/pan_end2.mp3');
  32. }
  33. void initialize() {}
  34. void dispose() {
  35. _lifecycleNotifier?.removeListener(_handleAppLifecycle);
  36. stopMusic();
  37. stopSound();
  38. }
  39. /// Enables the [AudioController] to listen to [AppLifecycleState] events,
  40. /// and therefore do things like stopping playback when the game
  41. /// goes into the background.
  42. void attachLifecycleNotifier(ValueNotifier<AppLifecycleState> lifecycleNotifier) {
  43. _lifecycleNotifier?.removeListener(_handleAppLifecycle);
  44. lifecycleNotifier.addListener(_handleAppLifecycle);
  45. _lifecycleNotifier = lifecycleNotifier;
  46. }
  47. /// Enables the [AudioController] to track changes to settings.
  48. /// Namely, when any of [SettingsController.muted],
  49. /// [SettingsController.musicOn] or [SettingsController.soundsOn] changes,
  50. /// the audio controller will act accordingly.
  51. void attachSettings(SettingsController settingsController) {
  52. if (_settings == settingsController) {
  53. // Already attached to this instance. Nothing to do.
  54. return;
  55. }
  56. // Remove handlers from the old settings controller if present
  57. final oldSettings = _settings;
  58. if (oldSettings != null) {
  59. oldSettings.music.removeListener(_musicOnHandler);
  60. oldSettings.sound.removeListener(_soundOnHandler);
  61. }
  62. _settings = settingsController;
  63. // Add handlers to the new settings controller
  64. settingsController.music.addListener(_musicOnHandler);
  65. settingsController.sound.addListener(_soundOnHandler);
  66. }
  67. /// Plays a single sound effect, defined by [type].
  68. ///
  69. /// The controller will ignore this call when the attached settings'
  70. /// [SettingsController.soundsOn] is `false`.
  71. void playSfx(SfxType type, {Duration? duration}) async {
  72. final soundsOn = _settings?.sound.value ?? false;
  73. if (!soundsOn) {
  74. _log.info(() => 'Ignoring playing sound ($type) because sounds are turned off.');
  75. return;
  76. }
  77. _audioPlayer.playSound(type.index);
  78. if (duration != null) {
  79. Future.delayed(duration, () => _audioPlayer.stopSound());
  80. }
  81. }
  82. void _handleAppLifecycle() {
  83. _log.info(_lifecycleNotifier!.value);
  84. switch (_lifecycleNotifier!.value) {
  85. case AppLifecycleState.paused:
  86. case AppLifecycleState.detached:
  87. case AppLifecycleState.hidden:
  88. case AppLifecycleState.inactive:
  89. pauseMusic();
  90. break;
  91. case AppLifecycleState.resumed:
  92. resumeMusic();
  93. break;
  94. }
  95. }
  96. void _musicOnHandler() {
  97. if (_settings!.music.value) {
  98. // Music got turned on.
  99. // _resumeMusic();
  100. startMusic();
  101. } else {
  102. // Music got turned off.
  103. stopMusic();
  104. }
  105. }
  106. void _soundOnHandler() {}
  107. void startMusic() {
  108. _log.info('starting music');
  109. final musicOn = _settings?.music.value ?? false;
  110. if (!musicOn) {
  111. _log.info(() => 'Ignoring playing music because music are turned off.');
  112. return;
  113. }
  114. _audioPlayer.playMusic(1, volume: 0.1);
  115. }
  116. void stopMusic() {
  117. _log.info('Stopping music');
  118. _audioPlayer.stopMusic();
  119. }
  120. void pauseMusic() {
  121. _log.info('pause music');
  122. _audioPlayer.pauseMusic();
  123. }
  124. Future<void> resumeMusic() async {
  125. _log.info('Resuming music');
  126. final musicOn = _settings?.music.value ?? false;
  127. if (musicOn) {
  128. _audioPlayer.resumeMusic();
  129. }
  130. }
  131. void stopSound() {
  132. _audioPlayer.stopSound();
  133. }
  134. }