neoagent 2.3.1-beta.20 → 2.3.1-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/flutter_app/.metadata +42 -0
  2. package/flutter_app/README.md +21 -0
  3. package/flutter_app/analysis_options.yaml +32 -0
  4. package/flutter_app/android/app/build.gradle.kts +109 -0
  5. package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
  6. package/flutter_app/android/app/src/main/AndroidManifest.xml +147 -0
  7. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +747 -0
  8. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
  9. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
  10. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
  11. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
  12. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
  13. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
  14. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
  15. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
  16. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
  17. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
  18. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
  19. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
  20. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
  21. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
  22. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
  23. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
  24. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
  25. package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
  26. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
  27. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
  28. package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  29. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
  30. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
  31. package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
  32. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  33. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  34. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  35. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  36. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  37. package/flutter_app/android/app/src/main/res/values/strings.xml +12 -0
  38. package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
  39. package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
  40. package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
  41. package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
  42. package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
  43. package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
  44. package/flutter_app/android/build.gradle.kts +24 -0
  45. package/flutter_app/android/ci-release.keystore +0 -0
  46. package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  47. package/flutter_app/android/gradle.properties +3 -0
  48. package/flutter_app/android/key.properties +4 -0
  49. package/flutter_app/android/settings.gradle.kts +26 -0
  50. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  51. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  52. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  53. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  54. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  55. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  56. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  57. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  58. package/flutter_app/lib/features/location/location_service.dart +119 -0
  59. package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
  60. package/flutter_app/lib/main.dart +23057 -0
  61. package/flutter_app/lib/main_app_shell.dart +1682 -0
  62. package/flutter_app/lib/main_integrations.dart +931 -0
  63. package/flutter_app/lib/main_launcher.dart +959 -0
  64. package/flutter_app/lib/main_launcher_entry.dart +5 -0
  65. package/flutter_app/lib/main_models.dart +3473 -0
  66. package/flutter_app/lib/main_shared.dart +2861 -0
  67. package/flutter_app/lib/main_theme.dart +204 -0
  68. package/flutter_app/lib/main_voice_assistant.dart +831 -0
  69. package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
  70. package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
  71. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
  72. package/flutter_app/lib/src/android_app_installer.dart +22 -0
  73. package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
  74. package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
  75. package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
  76. package/flutter_app/lib/src/app_launch_bridge.dart +29 -0
  77. package/flutter_app/lib/src/app_release_updater.dart +511 -0
  78. package/flutter_app/lib/src/backend_client.dart +1833 -0
  79. package/flutter_app/lib/src/desktop_companion.dart +2 -0
  80. package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
  81. package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
  82. package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
  83. package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
  84. package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
  85. package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
  86. package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
  87. package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
  88. package/flutter_app/lib/src/health_bridge.dart +136 -0
  89. package/flutter_app/lib/src/live_voice_capture.dart +85 -0
  90. package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
  91. package/flutter_app/lib/src/network/app_http_client.dart +53 -0
  92. package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
  93. package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
  94. package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
  95. package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
  96. package/flutter_app/lib/src/oauth_launcher.dart +33 -0
  97. package/flutter_app/lib/src/oauth_launcher_io.dart +77 -0
  98. package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
  99. package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
  100. package/flutter_app/lib/src/recording_bridge.dart +232 -0
  101. package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
  102. package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
  103. package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
  104. package/flutter_app/lib/src/recording_payloads.dart +86 -0
  105. package/flutter_app/lib/src/theme/palette.dart +81 -0
  106. package/flutter_app/lib/src/widget_bridge.dart +49 -0
  107. package/flutter_app/linux/CMakeLists.txt +128 -0
  108. package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
  109. package/flutter_app/linux/flutter/generated_plugin_registrant.cc +43 -0
  110. package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
  111. package/flutter_app/linux/flutter/generated_plugins.cmake +31 -0
  112. package/flutter_app/linux/runner/CMakeLists.txt +26 -0
  113. package/flutter_app/linux/runner/main.cc +6 -0
  114. package/flutter_app/linux/runner/my_application.cc +144 -0
  115. package/flutter_app/linux/runner/my_application.h +18 -0
  116. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  117. package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
  118. package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
  119. package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +40 -0
  120. package/flutter_app/macos/Podfile +42 -0
  121. package/flutter_app/macos/Podfile.lock +87 -0
  122. package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
  123. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  124. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  125. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  126. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  127. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  128. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  129. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  130. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  131. package/flutter_app/macos/Runner/Base.lproj/MainMenu.xib +342 -0
  132. package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  133. package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
  134. package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
  135. package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
  136. package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
  137. package/flutter_app/macos/Runner/Info.plist +36 -0
  138. package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
  139. package/flutter_app/macos/Runner/Release.entitlements +12 -0
  140. package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
  141. package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  142. package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
  143. package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  144. package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  145. package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
  146. package/flutter_app/patch_strings.py +12 -0
  147. package/flutter_app/pubspec.lock +1088 -0
  148. package/flutter_app/pubspec.yaml +53 -0
  149. package/flutter_app/test/messaging_access_summary_test.dart +22 -0
  150. package/flutter_app/test/recording_payloads_test.dart +53 -0
  151. package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
  152. package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
  153. package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
  154. package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
  155. package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
  156. package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
  157. package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
  158. package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
  159. package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
  160. package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
  161. package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
  162. package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
  163. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
  164. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
  165. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
  166. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
  167. package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
  168. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
  169. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
  170. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
  171. package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
  172. package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
  173. package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
  174. package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
  175. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
  176. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
  177. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
  178. package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
  179. package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
  180. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
  181. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
  182. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
  183. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
  184. package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
  185. package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
  186. package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
  187. package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
  188. package/flutter_app/tool/generate_desktop_branding.py +219 -0
  189. package/flutter_app/web/favicon.png +0 -0
  190. package/flutter_app/web/favicon.svg +12 -0
  191. package/flutter_app/web/icons/Icon-192.png +0 -0
  192. package/flutter_app/web/icons/Icon-512.png +0 -0
  193. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  194. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  195. package/flutter_app/web/index.html +39 -0
  196. package/flutter_app/web/manifest.json +35 -0
  197. package/flutter_app/windows/CMakeLists.txt +108 -0
  198. package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
  199. package/flutter_app/windows/flutter/generated_plugin_registrant.cc +47 -0
  200. package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
  201. package/flutter_app/windows/flutter/generated_plugins.cmake +35 -0
  202. package/flutter_app/windows/runner/CMakeLists.txt +41 -0
  203. package/flutter_app/windows/runner/Runner.rc +121 -0
  204. package/flutter_app/windows/runner/flutter_window.cpp +533 -0
  205. package/flutter_app/windows/runner/flutter_window.h +37 -0
  206. package/flutter_app/windows/runner/main.cpp +53 -0
  207. package/flutter_app/windows/runner/resource.h +16 -0
  208. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  209. package/flutter_app/windows/runner/runner.exe.manifest +14 -0
  210. package/flutter_app/windows/runner/utils.cpp +65 -0
  211. package/flutter_app/windows/runner/utils.h +19 -0
  212. package/flutter_app/windows/runner/win32_window.cpp +299 -0
  213. package/flutter_app/windows/runner/win32_window.h +102 -0
  214. package/package.json +2 -1
  215. package/server/public/flutter_bootstrap.js +1 -1
@@ -0,0 +1,53 @@
1
+ name: neoagent_flutter
2
+ description: NeoAgent client for Flutter web, Android, Windows, macOS, and Linux.
3
+ publish_to: none
4
+ version: 1.0.0+1
5
+
6
+ environment:
7
+ sdk: ^3.9.2
8
+
9
+ dependencies:
10
+ flutter:
11
+ sdk: flutter
12
+ cupertino_icons: ^1.0.8
13
+ flutter_markdown: ^0.7.4+1
14
+ google_fonts: ^6.3.1
15
+ image: ^4.5.4
16
+ http: ^1.5.0
17
+ connectivity_plus: 6.1.5
18
+ shared_preferences: ^2.5.3
19
+ flutter_secure_storage: ^9.2.2
20
+ socket_io_client: ^3.1.2
21
+ universal_ble: ^1.1.0
22
+ permission_handler: ^12.0.1
23
+ path_provider: ^2.1.5
24
+ package_info_plus: ^8.3.1
25
+ audioplayers: ^6.1.0
26
+ qr_flutter: ^4.1.0
27
+ record: ^6.1.1
28
+ window_manager: ^0.5.1
29
+ tray_manager: ^0.5.2
30
+ hotkey_manager: ^0.2.3
31
+ desktop_audio_capture:
32
+ path: third_party/desktop_audio_capture
33
+ launch_at_startup: ^0.5.1
34
+ mobile_scanner: ^7.2.0
35
+ geolocator: ^13.0.2
36
+ flutter_background_service: ^5.1.0
37
+ notification_listener_service: ^0.3.5
38
+
39
+ dependency_overrides:
40
+ flutter_secure_storage_linux:
41
+ path: third_party/flutter_secure_storage_linux
42
+
43
+ dev_dependencies:
44
+ flutter_test:
45
+ sdk: flutter
46
+ flutter_lints: ^5.0.0
47
+
48
+ flutter:
49
+ uses-material-design: true
50
+ assets:
51
+ - web/icons/Icon-192.png
52
+ - assets/branding/app_icon_256.png
53
+ - assets/branding/tray_icon_template.png
@@ -0,0 +1,22 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:flutter_test/flutter_test.dart';
3
+ import 'package:neoagent_flutter/src/messaging_access_summary.dart';
4
+
5
+ void main() {
6
+ testWidgets('renders policy summary and hint', (tester) async {
7
+ await tester.pumpWidget(
8
+ MaterialApp(
9
+ home: Scaffold(
10
+ body: MessagingAccessSummaryCard(
11
+ accent: const Color(0xFF5865F2),
12
+ summary: 'DMs allowlist • shared allowlist • mentions required • 3 rules',
13
+ hint: 'Add users, channels, or roles.',
14
+ ),
15
+ ),
16
+ ),
17
+ );
18
+
19
+ expect(find.textContaining('DMs allowlist'), findsOneWidget);
20
+ expect(find.text('Add users, channels, or roles.'), findsOneWidget);
21
+ });
22
+ }
@@ -0,0 +1,53 @@
1
+ import 'package:flutter_test/flutter_test.dart';
2
+ import 'package:neoagent_flutter/src/recording_payloads.dart';
3
+
4
+ void main() {
5
+ group('recording payload builders', () {
6
+ test('web screen and mic payload keeps both sources', () {
7
+ final payload = buildWebScreenAndMicRecordingPayload();
8
+ final sources = payload['sources'] as List<dynamic>;
9
+
10
+ expect(payload['platform'], 'web');
11
+ expect(payload['screenAnalysisReady'], true);
12
+ expect(sources, hasLength(2));
13
+ expect(
14
+ sources.map((item) => (item as Map<String, dynamic>)['sourceKey']),
15
+ containsAll(<String>['screen', 'microphone']),
16
+ );
17
+ });
18
+
19
+ test('android background payload keeps background metadata', () {
20
+ final payload = buildAndroidBackgroundRecordingPayload();
21
+ final source = (payload['sources'] as List<dynamic>).single
22
+ as Map<String, dynamic>;
23
+
24
+ expect(payload['platform'], 'android');
25
+ expect(source['sourceKey'], 'microphone');
26
+ expect(source['mimeType'], 'audio/wav');
27
+ expect(
28
+ (source['metadata'] as Map<String, dynamic>)['backgroundCapable'],
29
+ true,
30
+ );
31
+ });
32
+
33
+ test('desktop payload advertises dual-source desktop capture metadata', () {
34
+ final payload = buildDesktopRecordingPayload();
35
+ final sources = (payload['sources'] as List<dynamic>)
36
+ .cast<Map<String, dynamic>>();
37
+ final systemSource = sources.firstWhere(
38
+ (source) => source['sourceKey'] == 'system',
39
+ );
40
+
41
+ expect(payload['platform'], 'desktop');
42
+ expect(payload['capturePlan'], 'desktop-dual-source');
43
+ expect(
44
+ sources.map((source) => source['sourceKey']),
45
+ containsAll(<String>['microphone', 'system']),
46
+ );
47
+ expect(
48
+ (systemSource['metadata'] as Map<String, dynamic>)['globalHotkeyReady'],
49
+ true,
50
+ );
51
+ });
52
+ });
53
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 desktop_audio_capture
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,262 @@
1
+ # desktop_audio_capture
2
+
3
+ A Flutter plugin for capturing audio on desktop platforms (macOS, Linux, Windows). Supports capturing from microphone and system audio with features like audio data streaming, decibel monitoring, device management, and permission handling.
4
+
5
+ ## Features
6
+
7
+ - 🎤 **Microphone Capture**: Capture audio from microphone with flexible configuration
8
+ - 🔊 **System Audio Capture**: Capture audio from system (system audio)
9
+ - 📊 **Decibel Monitoring**: Real-time audio level monitoring
10
+ - 🎛️ **Device Management**: List and manage available input devices
11
+ - ⚙️ **Configurable**: Configure sample rate, channels, bit depth, gain boost
12
+ - 🔐 **Permissions Handling**: Automatic permission handling for microphone and screen recording
13
+
14
+ ## Platform Support
15
+
16
+ - ✅ **macOS 13.0+** (Ventura or later) - Fully tested and working
17
+ - ✅ **Linux** - Supported
18
+ - ✅ **Windows** - Supported
19
+
20
+ > **Note**:
21
+ > - macOS requires **macOS 13.0 (Ventura) or later** because System Audio Capture uses APIs available from macOS 13.0+
22
+
23
+ ## Screenshots
24
+
25
+ ### Home Screen
26
+ ![Example Home](doc/example_home.png)
27
+
28
+ ### Microphone Settings
29
+ ![Example Setting Mic](doc/example_setting_mic.png)
30
+
31
+ ### System Audio Settings
32
+ ![Example Setting System](doc/example_setting_system.png)
33
+
34
+ ## Installation
35
+
36
+ Add the dependency to your `pubspec.yaml`:
37
+
38
+ ```yaml
39
+ dependencies:
40
+ desktop_audio_capture: ^0.0.1
41
+ ```
42
+
43
+ Then run:
44
+
45
+ ```bash
46
+ flutter pub get
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Microphone Capture
52
+
53
+ ```dart
54
+ import 'package:desktop_audio_capture/audio_capture.dart';
55
+
56
+ // Create instance
57
+ final micCapture = MicAudioCapture(
58
+ config: MicAudioConfig(
59
+ sampleRate: 16000,
60
+ channels: 1,
61
+ bitDepth: 16,
62
+ gainBoost: 2.5,
63
+ inputVolume: 1.0,
64
+ ),
65
+ );
66
+
67
+ // Start capture
68
+ await micCapture.startCapture();
69
+
70
+ // Listen to audio stream
71
+ micCapture.audioStream?.listen((audioData) {
72
+ // Process audio data (Uint8List)
73
+ print('Received ${audioData.length} bytes');
74
+ });
75
+
76
+ // Listen to decibel readings
77
+ micCapture.decibelStream?.listen((decibelData) {
78
+ print('Decibel: ${decibelData.decibel} dB');
79
+ print('Timestamp: ${decibelData.timestamp}');
80
+ });
81
+
82
+ // Listen to status updates
83
+ micCapture.statusStream?.listen((status) {
84
+ print('Mic active: ${status.isActive}');
85
+ if (status.deviceName != null) {
86
+ print('Device: ${status.deviceName}');
87
+ }
88
+ });
89
+
90
+ // Stop capture
91
+ await micCapture.stopCapture();
92
+ ```
93
+
94
+ ### System Audio Capture
95
+
96
+ ```dart
97
+ import 'package:desktop_audio_capture/audio_capture.dart';
98
+
99
+ // Create instance
100
+ final systemCapture = SystemAudioCapture(
101
+ config: SystemAudioConfig(
102
+ sampleRate: 44100,
103
+ channels: 2,
104
+ ),
105
+ );
106
+
107
+ // Start capture
108
+ await systemCapture.startCapture();
109
+
110
+ // Listen to audio stream
111
+ systemCapture.audioStream?.listen((audioData) {
112
+ // Process audio data (Uint8List)
113
+ print('Received ${audioData.length} bytes');
114
+ });
115
+
116
+ // Listen to decibel readings
117
+ systemCapture.decibelStream?.listen((decibelData) {
118
+ print('Decibel: ${decibelData.decibel} dB');
119
+ print('Timestamp: ${decibelData.timestamp}');
120
+ });
121
+
122
+ // Listen to status updates
123
+ systemCapture.statusStream?.listen((status) {
124
+ print('System audio active: ${status.isActive}');
125
+ });
126
+
127
+ // Stop capture
128
+ await systemCapture.stopCapture();
129
+ ```
130
+
131
+ ### Device Management (Microphone)
132
+
133
+ ```dart
134
+ // Check if input device is available
135
+ final hasDevice = await micCapture.hasInputDevice();
136
+
137
+ // Get list of available devices
138
+ final devices = await micCapture.getAvailableInputDevices();
139
+ for (final device in devices) {
140
+ print('Device: ${device.name}');
141
+ print('Type: ${device.type.toString()}');
142
+ print('Channels: ${device.channelCount}');
143
+ print('Default: ${device.isDefault}');
144
+ }
145
+ ```
146
+
147
+ ## API Reference
148
+
149
+ ### MicAudioCapture
150
+
151
+ #### Methods
152
+
153
+ - `startCapture({MicAudioConfig? config})`: Start capturing from microphone
154
+ - `stopCapture()`: Stop capture
155
+ - `requestPermissions()`: Request microphone access permission
156
+ - `hasInputDevice()`: Check if input device is available
157
+ - `getAvailableInputDevices()`: Get list of available input devices
158
+ - `updateConfig(MicAudioConfig config)`: Update configuration
159
+
160
+ #### Streams
161
+
162
+ - `audioStream`: Stream of audio data (Uint8List)
163
+ - `decibelStream`: Stream of decibel readings (DecibelData)
164
+ - `statusStream`: Stream of status updates (MicAudioStatus)
165
+
166
+ #### Properties
167
+
168
+ - `isRecording`: Whether currently recording or not
169
+
170
+ ### SystemAudioCapture
171
+
172
+ #### Methods
173
+
174
+ - `startCapture({SystemAudioConfig? config})`: Start capturing system audio
175
+ - `stopCapture()`: Stop capture
176
+ - `requestPermissions()`: Request screen recording permission (macOS)
177
+ - `updateConfig(SystemAudioConfig config)`: Update configuration
178
+
179
+ #### Streams
180
+
181
+ - `audioStream`: Stream of audio data (Uint8List)
182
+ - `decibelStream`: Stream of decibel readings (DecibelData)
183
+ - `statusStream`: Stream of status updates (SystemAudioStatus)
184
+
185
+ #### Properties
186
+
187
+ - `isRecording`: Whether currently recording or not
188
+
189
+ ### MicAudioConfig
190
+
191
+ - `sampleRate` (int): Sample rate (default: 16000 Hz)
192
+ - `channels` (int): Number of audio channels (default: 1)
193
+ - `bitDepth` (int): Bit depth (default: 16)
194
+ - `gainBoost` (double): Gain boost multiplier (default: 2.5, range: 0.1-10.0)
195
+ - `inputVolume` (double): Input volume (default: 1.0, range: 0.0-1.0)
196
+
197
+ ### SystemAudioConfig
198
+
199
+ - `sampleRate` (int): Sample rate (default: 16000 Hz)
200
+ - `channels` (int): Number of audio channels (default: 1)
201
+
202
+ ### DecibelData
203
+
204
+ - `decibel` (double): Decibel value (-120 to 0 dB)
205
+ - `timestamp` (double): Unix timestamp in seconds
206
+
207
+ ### MicAudioStatus
208
+
209
+ - `isActive` (bool): Whether microphone capture is currently active
210
+ - `deviceName` (String?): Name of the microphone device (if available)
211
+
212
+ ### SystemAudioStatus
213
+
214
+ - `isActive` (bool): Whether system audio capture is currently active
215
+
216
+ ### InputDevice
217
+
218
+ - `id` (String): Unique identifier of the device
219
+ - `name` (String): Human-readable name of the device
220
+ - `type` (InputDeviceType): Type of device (builtIn, bluetooth, external)
221
+ - `channelCount` (int): Number of audio channels supported
222
+ - `isDefault` (bool): Whether this device is the system default input device
223
+
224
+ ## Permissions
225
+
226
+ ### macOS (13.0+)
227
+
228
+ **System Requirements**: macOS 13.0 (Ventura) or later is required.
229
+
230
+ - **Microphone**: Requires microphone access permission in `Info.plist`:
231
+ ```xml
232
+ <key>NSMicrophoneUsageDescription</key>
233
+ <string>This app needs access to the microphone to capture audio.</string>
234
+ ```
235
+
236
+ - **System Audio**: Requires Screen Recording permission in System Preferences. Add to `Info.plist`:
237
+ ```xml
238
+ <key>NSScreenCaptureDescription</key>
239
+ <string>This app needs Screen Recording permission to capture system audio.</string>
240
+ ```
241
+
242
+ After adding to `Info.plist`, users need to grant permission in **System Preferences > Security & Privacy > Screen Recording**.
243
+
244
+ ### Linux
245
+
246
+ - Requires access to audio devices (usually automatic)
247
+
248
+ ### Windows
249
+
250
+ - Requires microphone access (usually automatic)
251
+
252
+ ## Example
253
+
254
+ See detailed example in the [example](example/) directory.
255
+
256
+ ## License
257
+
258
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
259
+
260
+ ## Homepage
261
+
262
+ [https://github.com/hiuhuyn/desktop_audio_capture](https://github.com/hiuhuyn/desktop_audio_capture)
@@ -0,0 +1,65 @@
1
+ // You have generated a new plugin project without specifying the `--platforms`
2
+ // flag. A plugin project with no platform support was generated. To add a
3
+ // platform, run `flutter create -t plugin --platforms <platforms> .` under the
4
+ // same directory. You can also find a detailed instruction on how to add
5
+ // platforms in the `pubspec.yaml` at
6
+ // https://flutter.dev/to/pubspec-plugin-platforms.
7
+
8
+ export 'package:desktop_audio_capture/mic/mic_audio_capture.dart';
9
+ export 'package:desktop_audio_capture/system/system_audio_capture.dart';
10
+
11
+ // Re-export DecibelData from mic_audio_capture (both mic and system use the same class)
12
+ export 'package:desktop_audio_capture/model/decibel_data.dart';
13
+ export 'package:desktop_audio_capture/model/input_device_type.dart';
14
+ export 'package:desktop_audio_capture/model/audio_status.dart';
15
+
16
+ /// Abstract base class for audio capture functionality.
17
+ ///
18
+ /// This class defines the common interface for capturing audio from different sources
19
+ /// (microphone or system audio). Implementations include [MicAudioCapture] and
20
+ /// [SystemAudioCapture].
21
+ ///
22
+ /// Example:
23
+ /// ```dart
24
+ /// final audioCapture = MicAudioCapture();
25
+ /// await audioCapture.initialize();
26
+ /// await audioCapture.startCapture();
27
+ ///
28
+ /// // Listen to audio stream
29
+ /// audioCapture.audioStream?.listen((audioData) {
30
+ /// // Process audio data
31
+ /// });
32
+ ///
33
+ /// // Stop when done
34
+ /// await audioCapture.stopCapture();
35
+ /// await audioCapture.dispose();
36
+ /// ```
37
+ abstract class AudioCapture {
38
+ /// Whether the audio capture is currently recording.
39
+ ///
40
+ /// Returns `true` if capture is active, `false` otherwise.
41
+ ///
42
+ /// Example:
43
+ /// ```dart
44
+ /// if (audioCapture.isRecording) {
45
+ /// print('Audio capture is active');
46
+ /// }
47
+ /// ```
48
+ bool get isRecording;
49
+ }
50
+
51
+ /// Abstract base class for audio capture configuration.
52
+ ///
53
+ /// This class defines the common interface for configuration objects used
54
+ /// to configure audio capture settings. Implementations include [MicAudioConfig]
55
+ /// and [SystemAudioConfig].
56
+ ///
57
+ /// Example:
58
+ /// ```dart
59
+ /// final config = MicAudioConfig(
60
+ /// sampleRate: 44100,
61
+ /// channels: 2,
62
+ /// );
63
+ /// final capture = MicAudioCapture(config: config);
64
+ /// ```
65
+ abstract class AudioCaptureConfig {}
@@ -0,0 +1,153 @@
1
+ import 'package:desktop_audio_capture/audio_capture.dart';
2
+
3
+ /// Configuration class for microphone audio capture.
4
+ ///
5
+ /// This class allows you to configure various audio capture parameters
6
+ /// such as sample rate, channels, bit depth, gain boost, and input volume.
7
+ ///
8
+ /// Example:
9
+ /// ```dart
10
+ /// // Create with default values
11
+ /// final config = MicAudioConfig();
12
+ ///
13
+ /// // Create with custom values
14
+ /// final customConfig = MicAudioConfig(
15
+ /// sampleRate: 44100,
16
+ /// channels: 2,
17
+ /// bitDepth: 24,
18
+ /// gainBoost: 3.0,
19
+ /// inputVolume: 0.8,
20
+ /// );
21
+ ///
22
+ /// // Use with capture
23
+ /// final capture = MicAudioCapture(config: customConfig);
24
+ ///
25
+ /// // Update configuration
26
+ /// final updatedConfig = customConfig.copyWith(
27
+ /// gainBoost: 2.5,
28
+ /// inputVolume: 1.0,
29
+ /// );
30
+ /// capture.updateConfig(updatedConfig);
31
+ /// ```
32
+ class MicAudioConfig extends AudioCaptureConfig {
33
+ /// Sample rate in Hz (default: 16000).
34
+ ///
35
+ /// Common values: 8000, 16000, 44100, 48000.
36
+ /// Higher sample rates provide better quality but use more resources.
37
+ final int sampleRate;
38
+
39
+ /// Number of audio channels (default: 1 for mono).
40
+ ///
41
+ /// - 1: Mono (single channel)
42
+ /// - 2: Stereo (two channels)
43
+ final int channels;
44
+
45
+ /// Bit depth (default: 16).
46
+ ///
47
+ /// Common values: 16, 24, 32.
48
+ /// Higher bit depth provides better dynamic range.
49
+ final int bitDepth;
50
+
51
+ /// Gain boost multiplier (default: 2.5, range: 0.1 to 10.0).
52
+ ///
53
+ /// Higher values increase microphone sensitivity and amplify the input signal.
54
+ /// Use with caution as very high values may cause distortion.
55
+ final double gainBoost;
56
+
57
+ /// Input volume (default: 1.0, range: 0.0 to 1.0).
58
+ ///
59
+ /// Controls the input volume level:
60
+ /// - 0.0: Muted
61
+ /// - 0.5: Half volume
62
+ /// - 1.0: Full volume
63
+ final double inputVolume;
64
+
65
+ /// Creates a new [MicAudioConfig] instance.
66
+ ///
67
+ /// All parameters are optional and have default values:
68
+ /// - [sampleRate]: 16000
69
+ /// - [channels]: 1
70
+ /// - [bitDepth]: 16
71
+ /// - [gainBoost]: 2.5
72
+ /// - [inputVolume]: 1.0
73
+ ///
74
+ /// Example:
75
+ /// ```dart
76
+ /// final config = MicAudioConfig(
77
+ /// sampleRate: 44100,
78
+ /// channels: 1,
79
+ /// gainBoost: 2.0,
80
+ /// );
81
+ /// ```
82
+ MicAudioConfig({
83
+ this.sampleRate = 16000,
84
+ this.channels = 1,
85
+ this.bitDepth = 16,
86
+ this.gainBoost = 2.5,
87
+ this.inputVolume = 1.0,
88
+ });
89
+
90
+ /// Creates a copy of this configuration with modified values.
91
+ ///
92
+ /// Only the specified parameters will be changed; others remain the same.
93
+ ///
94
+ /// Example:
95
+ /// ```dart
96
+ /// final config = MicAudioConfig(
97
+ /// sampleRate: 16000,
98
+ /// gainBoost: 2.5,
99
+ /// );
100
+ ///
101
+ /// // Increase gain boost while keeping other values
102
+ /// final updated = config.copyWith(gainBoost: 3.0);
103
+ /// // updated.sampleRate is still 16000
104
+ /// ```
105
+ MicAudioConfig copyWith({
106
+ int? sampleRate,
107
+ int? channels,
108
+ int? bitDepth,
109
+ double? gainBoost,
110
+ double? inputVolume,
111
+ }) {
112
+ return MicAudioConfig(
113
+ sampleRate: sampleRate ?? this.sampleRate,
114
+ channels: channels ?? this.channels,
115
+ bitDepth: bitDepth ?? this.bitDepth,
116
+ gainBoost: gainBoost ?? this.gainBoost,
117
+ inputVolume: inputVolume ?? this.inputVolume,
118
+ );
119
+ }
120
+
121
+ /// Converts this configuration to a map for method channel communication.
122
+ ///
123
+ /// Returns a map containing all configuration values:
124
+ /// - `sampleRate`: int
125
+ /// - `channels`: int
126
+ /// - `bitDepth`: int
127
+ /// - `gainBoost`: double
128
+ /// - `inputVolume`: double
129
+ ///
130
+ /// Example:
131
+ /// ```dart
132
+ /// final config = MicAudioConfig(
133
+ /// sampleRate: 44100,
134
+ /// channels: 2,
135
+ /// );
136
+ /// final map = config.toMap();
137
+ /// // map = {'sampleRate': 44100, 'channels': 2, 'bitDepth': 16, 'gainBoost': 2.5, 'inputVolume': 1.0}
138
+ /// ```
139
+ Map<String, dynamic> toMap() {
140
+ return {
141
+ 'sampleRate': sampleRate,
142
+ 'channels': channels,
143
+ 'bitDepth': bitDepth,
144
+ 'gainBoost': gainBoost,
145
+ 'inputVolume': inputVolume,
146
+ };
147
+ }
148
+
149
+ @override
150
+ String toString() {
151
+ return 'MicConfig(sampleRate: $sampleRate, channels: $channels, bitDepth: $bitDepth, gainBoost: $gainBoost, inputVolume: $inputVolume)';
152
+ }
153
+ }