com.amanotes.gdk 0.2.65-2 → 0.2.65-3

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 (39) hide show
  1. package/Editor/Extra/GDKLocalBuild.cs +24 -57
  2. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  3. package/Extra/CheckDiskSpace.unitypackage +0 -0
  4. package/Extra/ForceUpdate.unitypackage +0 -0
  5. package/Extra/GoogleCMP.unitypackage +0 -0
  6. package/Extra/PostProcessor.unitypackage +0 -0
  7. package/Extra/SDKVersionTracking.unitypackage +0 -0
  8. package/Packages/AmaGDKConfig.unitypackage +0 -0
  9. package/Packages/AmaGDKExample.unitypackage +0 -0
  10. package/Packages/AmaGDKTest.unitypackage +0 -0
  11. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
  12. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  13. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  14. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  15. package/Packages/IronSourceAdapter.unitypackage +0 -0
  16. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  17. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  18. package/Runtime/AmaGDK.Analytics.cs +10 -4
  19. package/Runtime/AmaGDK.Mono.cs +0 -2
  20. package/Runtime/AmaGDK.UserProfile.cs +1 -1
  21. package/Runtime/AmaGDK.cs +2 -1
  22. package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs +165 -0
  23. package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs.meta +11 -0
  24. package/Runtime/AudioToolkit/AmaGDK.Audio.cs +158 -0
  25. package/Runtime/AudioToolkit/AmaGDK.Audio.cs.meta +11 -0
  26. package/Runtime/AudioToolkit/Plugins/Android/AudioDeviceDetector.java +321 -0
  27. package/Runtime/AudioToolkit/Plugins/Android/AudioDeviceDetector.java.meta +32 -0
  28. package/Runtime/AudioToolkit/Plugins/Android.meta +8 -0
  29. package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +204 -0
  30. package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs.meta +3 -0
  31. package/Runtime/AudioToolkit/Plugins/iOS/AudioDeviceDetector.mm +163 -0
  32. package/Runtime/AudioToolkit/Plugins/iOS/AudioDeviceDetector.mm.meta +33 -0
  33. package/Runtime/AudioToolkit/Plugins/iOS.meta +8 -0
  34. package/Runtime/AudioToolkit/Plugins.meta +8 -0
  35. package/Runtime/AudioToolkit/Resources/device-latency.txt +256 -0
  36. package/Runtime/AudioToolkit/Resources/device-latency.txt.meta +7 -0
  37. package/Runtime/AudioToolkit/Resources.meta +8 -0
  38. package/Runtime/AudioToolkit.meta +3 -0
  39. package/package.json +1 -1
@@ -0,0 +1,321 @@
1
+ package com.amanotes.audio;
2
+
3
+ import android.content.Context;
4
+ import android.media.AudioDeviceInfo;
5
+ import android.media.AudioDeviceCallback;
6
+ import android.media.AudioManager;
7
+ import android.media.MediaRouter;
8
+ import android.os.Build;
9
+ import android.util.Log;
10
+ import java.util.HashMap;
11
+ import java.util.Map;
12
+
13
+ import com.unity3d.player.UnityPlayer;
14
+
15
+ public class AudioDeviceDetector
16
+ {
17
+ private static boolean isRegistered = false;
18
+ private static boolean isFirstCallback = true;
19
+
20
+ private static final String PARAM_FORMAT = "%s;%s";
21
+ private static final String DEFAULT_HEADPHONE_NAME = "h2w";
22
+
23
+ private static MediaRouter.RouteInfo currentRoute;
24
+
25
+ private static final Map<Integer, String> DEVICE_TYPE_MAP = new HashMap<>();
26
+ static {
27
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_UNKNOWN, "TYPE_UNKNOWN");
28
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, "TYPE_BUILTIN_EARPIECE");
29
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "TYPE_BUILTIN_SPEAKER");
30
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, "TYPE_WIRED_HEADSET");
31
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, "TYPE_WIRED_HEADPHONES");
32
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_LINE_ANALOG, "TYPE_LINE_ANALOG");
33
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_LINE_DIGITAL, "TYPE_LINE_DIGITAL");
34
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
35
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, "TYPE_BLUETOOTH_A2DP");
36
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI, "TYPE_HDMI");
37
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI_ARC, "TYPE_HDMI_ARC");
38
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_DEVICE, "TYPE_USB_DEVICE");
39
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, "TYPE_USB_ACCESSORY");
40
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_DOCK, "TYPE_DOCK");
41
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_FM, "TYPE_FM");
42
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_MIC, "TYPE_BUILTIN_MIC");
43
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_FM_TUNER, "TYPE_FM_TUNER");
44
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_TV_TUNER, "TYPE_TV_TUNER");
45
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_TELEPHONY, "TYPE_TELEPHONY");
46
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_AUX_LINE, "TYPE_AUX_LINE");
47
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_IP, "TYPE_IP");
48
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUS, "TYPE_BUS");
49
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_HEADSET, "TYPE_USB_HEADSET");
50
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HEARING_AID, "TYPE_HEARING_AID");
51
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE, "TYPE_BUILTIN_SPEAKER_SAFE");
52
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_REMOTE_SUBMIX, "TYPE_REMOTE_SUBMIX");
53
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_HEADSET, "TYPE_BLE_HEADSET");
54
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_SPEAKER, "TYPE_BLE_SPEAKER");
55
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI_EARC, "TYPE_HDMI_EARC");
56
+ DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_BROADCAST, "TYPE_BLE_BROADCAST");
57
+ }
58
+
59
+ public static void registerEvents() {
60
+ if (isRegistered)
61
+ return;
62
+ isRegistered = true;
63
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
64
+ registerForVersionM();
65
+ } else {
66
+ registerForVersionBeforeM();
67
+ }
68
+ }
69
+
70
+ public static String getAudioInfo() {
71
+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
72
+ ? getActiveParamM()
73
+ : getActiveParamBeforeM();
74
+ }
75
+
76
+ private static void registerForVersionM() {
77
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
78
+ return;
79
+ Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
80
+ if (unityContext == null)
81
+ return;
82
+ AudioManager audioManager = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
83
+ if (audioManager == null)
84
+ return;
85
+
86
+ audioManager.registerAudioDeviceCallback(new AudioDeviceCallback() {
87
+ @Override
88
+ public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
89
+ super.onAudioDevicesAdded(addedDevices);
90
+ if (isFirstCallback) {
91
+ isFirstCallback = false;
92
+ return;
93
+ }
94
+ for (AudioDeviceInfo deviceInfo : addedDevices) {
95
+ if (deviceInfo == null)
96
+ continue;
97
+ if (deviceInfo.isSink()) {
98
+ String param = GetParamForDevice(deviceInfo);
99
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceAdded", param);
100
+ }
101
+ }
102
+ }
103
+
104
+ @Override
105
+ public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
106
+ super.onAudioDevicesRemoved(removedDevices);
107
+ for (AudioDeviceInfo deviceInfo : removedDevices) {
108
+ if (deviceInfo == null)
109
+ continue;
110
+ if (deviceInfo.isSink()) {
111
+ String param = GetParamForDevice(deviceInfo);
112
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", param);
113
+ }
114
+ }
115
+ }
116
+ }, null);
117
+
118
+ MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
119
+ if (mediaRouter == null)
120
+ return;
121
+ //listen to route change
122
+ mediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_AUDIO, new MediaRouter.SimpleCallback() {
123
+ @Override
124
+ public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
125
+ super.onRouteChanged(router, route);
126
+ //detect if change active device
127
+ if (route == router.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO))
128
+ return;
129
+ if (route.isEnabled() && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL && route.getPlaybackStream() == AudioManager.STREAM_MUSIC) {
130
+ //sent empty string to update current
131
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioRouteChanged", "");
132
+ currentRoute = route;
133
+ }
134
+ }
135
+
136
+ @Override
137
+ public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
138
+ super.onRouteRemoved(router, info);
139
+ //sent empty string to update current
140
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioRouteChanged", "");
141
+ currentRoute = info;
142
+ }
143
+ });
144
+ }
145
+
146
+ private static String getActiveParamM() {
147
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
148
+ return "";
149
+
150
+ Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
151
+ if (unityContext == null)
152
+ return "";
153
+
154
+ MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
155
+ if(mediaRouter == null)
156
+ return "";
157
+
158
+ AudioManager am = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
159
+ if (am == null)
160
+ return "";
161
+
162
+ if (currentRoute == null) {
163
+ currentRoute = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
164
+ }
165
+
166
+ AudioDeviceInfo device = null;
167
+ AudioDeviceInfo[] activeDevices = am.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
168
+
169
+ if(activeDevices == null || activeDevices.length == 0)
170
+ return "";
171
+
172
+ String name = currentRoute.getName() != null ? currentRoute.getName().toString() : "";
173
+ for (AudioDeviceInfo deviceInfo : activeDevices) {
174
+ int type = deviceInfo.getType();
175
+ if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)
176
+ continue;
177
+ if (isWiredDevice(type) || name.contentEquals(deviceInfo.getProductName())) {
178
+ device = deviceInfo;
179
+ break;
180
+ }
181
+ }
182
+
183
+ if(device != null)
184
+ return GetParamForDevice(device);
185
+
186
+ device = activeDevices[0];
187
+ for (AudioDeviceInfo deviceInfo : activeDevices) {
188
+ int type = deviceInfo.getType();
189
+ if (!deviceInfo.isSink())
190
+ continue;
191
+ if (am.isSpeakerphoneOn() && (type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE || type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)) {
192
+ device = deviceInfo;
193
+ break;
194
+ }
195
+ if (am.isBluetoothA2dpOn() && type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) {
196
+ device = deviceInfo;
197
+ break;
198
+ }
199
+ if (am.isBluetoothScoOn() && type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
200
+ device = deviceInfo;
201
+ break;
202
+ }
203
+ }
204
+
205
+ if (device == null)
206
+ return "";
207
+ return GetParamForDevice(device);
208
+ }
209
+
210
+ private static boolean isWiredDevice(int type)
211
+ {
212
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
213
+ {
214
+ return type == AudioDeviceInfo.TYPE_WIRED_HEADSET
215
+ || type == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
216
+ || type == AudioDeviceInfo.TYPE_LINE_ANALOG
217
+ || type == AudioDeviceInfo.TYPE_LINE_DIGITAL;
218
+ }
219
+
220
+ return false;
221
+ }
222
+
223
+ private static String GetParamForDevice(AudioDeviceInfo device)
224
+ {
225
+ if(device == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
226
+ return "";
227
+
228
+ int type = device.getType();
229
+ if (type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)
230
+ return "";
231
+
232
+ CharSequence name = device.getProductName();
233
+ if (isWiredDevice(type) || DEFAULT_HEADPHONE_NAME.contentEquals(name)) {
234
+ return getReturnParam("Headphones", toTypeString(type));
235
+ }
236
+ return getReturnParam(name, toTypeString(type));
237
+ }
238
+
239
+ private static String getReturnParam(CharSequence name, String type)
240
+ {
241
+ return String.format(PARAM_FORMAT, name, type);
242
+ }
243
+
244
+ private static String toTypeString(int AudioDeviceType)
245
+ {
246
+ return DEVICE_TYPE_MAP.getOrDefault(AudioDeviceType, "TYPE_UNKNOWN");
247
+ }
248
+
249
+ // API For Version before M
250
+ private static String getActiveParamBeforeM()
251
+ {
252
+ Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
253
+ if (unityContext == null)
254
+ return "";
255
+ AudioManager audioManager = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
256
+ if (audioManager == null)
257
+ return "";
258
+ MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
259
+ if (mediaRouter == null)
260
+ return "";
261
+
262
+ String type = "NOT_AVAILABLE";
263
+ MediaRouter.RouteInfo routeInfo = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
264
+ if (audioManager.isBluetoothA2dpOn())
265
+ type = "TYPE_BLUETOOTH_A2DP";
266
+ else if (audioManager.isBluetoothScoOn())
267
+ type = "TYPE_BLUETOOTH_SCO";
268
+ else if (audioManager.isSpeakerphoneOn())
269
+ type = "TYPE_BUILTIN_SPEAKER";
270
+ return getReturnParam(routeInfo.getName(), type);
271
+ }
272
+
273
+ private static void registerForVersionBeforeM()
274
+ {
275
+ Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
276
+ if (unityContext == null)
277
+ return;
278
+ MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
279
+ if (mediaRouter == null)
280
+ return;
281
+
282
+ mediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_AUDIO, new MediaRouter.SimpleCallback() {
283
+ @Override
284
+ public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
285
+ super.onRouteChanged(router, route);
286
+ //detect if change active device
287
+ if (route == router.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO))
288
+ return;
289
+ if (route.isEnabled() && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL && route.getPlaybackStream() == AudioManager.STREAM_MUSIC) {
290
+ UnityPlayer.UnitySendMessage("AmaGDK","OnAudioDeviceAdded", formatToParam(route));
291
+ }
292
+ }
293
+
294
+ @Override
295
+ public void onRouteSelected(MediaRouter router,int type, MediaRouter.RouteInfo info) {
296
+ super.onRouteRemoved(router, info);
297
+ UnityPlayer.UnitySendMessage("AmaGDK","OnAudioDeviceAdded", formatToParam(info));
298
+ }
299
+
300
+ @Override
301
+ public void onRouteUnselected(MediaRouter router,int type, MediaRouter.RouteInfo info) {
302
+ super.onRouteAdded(router, info);
303
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", formatToParam(info));
304
+ }
305
+
306
+ @Override
307
+ public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
308
+ super.onRouteRemoved(router, info);
309
+ UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", formatToParam(info));
310
+ }
311
+
312
+ private String formatToParam(MediaRouter.RouteInfo info)
313
+ {
314
+ if (info == null) return "";
315
+ String type = "NOT_AVAILABLE";
316
+ CharSequence name = info.getName();
317
+ return getReturnParam(name, type);
318
+ }
319
+ });
320
+ }
321
+ }
@@ -0,0 +1,32 @@
1
+ fileFormatVersion: 2
2
+ guid: 1db90e301ca5c40dcb36104b951a9cbc
3
+ PluginImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ iconMap: {}
7
+ executionOrder: {}
8
+ defineConstraints: []
9
+ isPreloaded: 0
10
+ isOverridable: 0
11
+ isExplicitlyReferenced: 0
12
+ validateReferences: 1
13
+ platformData:
14
+ - first:
15
+ Android: Android
16
+ second:
17
+ enabled: 1
18
+ settings: {}
19
+ - first:
20
+ Any:
21
+ second:
22
+ enabled: 0
23
+ settings: {}
24
+ - first:
25
+ Editor: Editor
26
+ second:
27
+ enabled: 0
28
+ settings:
29
+ DefaultValueInitialized: true
30
+ userData:
31
+ assetBundleName:
32
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: d562032f6a0e5441f9bacd35bca95d3f
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,204 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Runtime.InteropServices;
4
+ using System.Text;
5
+ using Amanotes.Core.Internal;
6
+ using UnityEngine;
7
+
8
+ namespace Amanotes.Core
9
+ {
10
+ internal class AudioDeviceDetector : MonoBehaviour
11
+ {
12
+ #if !UNITY_EDITOR && UNITY_IOS
13
+ [DllImport("__Internal")]
14
+ private static extern void _RegisterAudioInfoChanged();
15
+
16
+ [DllImport("__Internal")]
17
+ private static extern string _GetAudioInfo();
18
+
19
+ [DllImport("__Internal")]
20
+ private static extern string _GetCurrentRouteInputs();
21
+ #endif
22
+
23
+ #if !UNITY_EDITOR && UNITY_ANDROID
24
+ private readonly AndroidJavaClass _detectorClass = new AndroidJavaClass("com.amanotes.audio.AudioDeviceDetector");
25
+ #endif
26
+
27
+ private static readonly Dictionary<string, AudioDeviceType> deviceTypeMapping = new Dictionary<string, AudioDeviceType>(StringComparer.OrdinalIgnoreCase)
28
+ {
29
+ //iOS
30
+ { "AVAudioSessionPortAirPlay", AudioDeviceType.Wireless },
31
+ { "AVAudioSessionPortBluetoothA2DP", AudioDeviceType.Bluetooth },
32
+ { "AVAudioSessionPortBluetoothLE", AudioDeviceType.Bluetooth },
33
+ { "AVAudioSessionPortBluetoothHFP", AudioDeviceType.Bluetooth },
34
+ { "AVAudioSessionPortBuiltInReceiver", AudioDeviceType.Internal },
35
+ { "AVAudioSessionPortBuiltInSpeaker", AudioDeviceType.Internal },
36
+ { "AVAudioSessionPortHDMI", AudioDeviceType.Wire },
37
+ { "AVAudioSessionPortHeadphones", AudioDeviceType.Wire },
38
+ { "AVAudioSessionPortLineOut", AudioDeviceType.Wire },
39
+ { "AVAudioSessionPortDisplayPort", AudioDeviceType.Wire },
40
+ { "AVAudioSessionPortCarAudio", AudioDeviceType.Wire },
41
+ { "AVAudioSessionPortFireWire", AudioDeviceType.Wire },
42
+ { "AVAudioSessionPortPCI", AudioDeviceType.Wire },
43
+ { "AVAudioSessionPortThunderbolt", AudioDeviceType.Wire },
44
+ { "AVAudioSessionPortUSBAudio", AudioDeviceType.Wire },
45
+ { "AVAudioSessionPortVirtual", AudioDeviceType.Wire },
46
+ //Android
47
+ { "TYPE_BLUETOOTH_SCO", AudioDeviceType.Bluetooth },
48
+ { "TYPE_BLUETOOTH_A2DP", AudioDeviceType.Bluetooth },
49
+ { "TYPE_BLE_HEADSET", AudioDeviceType.Bluetooth },
50
+ { "TYPE_BLE_SPEAKER", AudioDeviceType.Bluetooth },
51
+ { "TYPE_BLE_BROADCAST", AudioDeviceType.Bluetooth },
52
+ { "TYPE_BUILTIN_SPEAKER_SAFE", AudioDeviceType.Internal },
53
+ { "TYPE_BUILTIN_MIC", AudioDeviceType.Internal },
54
+ { "TYPE_BUILTIN_EARPIECE", AudioDeviceType.Internal },
55
+ { "TYPE_BUILTIN_SPEAKER", AudioDeviceType.Internal },
56
+ { "TYPE_USB_HEADSET", AudioDeviceType.Wire },
57
+ { "TYPE_USB_DEVICE", AudioDeviceType.Wire },
58
+ { "TYPE_USB_ACCESSORY", AudioDeviceType.Wire },
59
+ { "TYPE_TELEPHONY", AudioDeviceType.Wire },
60
+ { "TYPE_LINE_ANALOG", AudioDeviceType.Wire },
61
+ { "TYPE_LINE_DIGITAL", AudioDeviceType.Wire },
62
+ { "TYPE_HDMI_ARC", AudioDeviceType.Wire },
63
+ { "TYPE_HDMI_EARC", AudioDeviceType.Wire },
64
+ { "TYPE_HDMI", AudioDeviceType.Wire },
65
+ { "TYPE_DOCK", AudioDeviceType.Wire },
66
+ { "TYPE_AUX_LINE", AudioDeviceType.Wire },
67
+ { "TYPE_WIRED_HEADSET", AudioDeviceType.Wire },
68
+ { "TYPE_WIRED_HEADPHONES", AudioDeviceType.Wire },
69
+ { "TYPE_FM", AudioDeviceType.Wireless },
70
+ { "TYPE_FM_TUNER", AudioDeviceType.Wireless },
71
+ { "TYPE_IP", AudioDeviceType.Wireless },
72
+ { "TYPE_REMOTE_SUBMIX", AudioDeviceType.Unknown },
73
+ { "TYPE_BUS", AudioDeviceType.Unknown },
74
+ { "TYPE_HEARING_AID", AudioDeviceType.Unknown },
75
+ { "TYPE_UNKNOWN", AudioDeviceType.Unknown },
76
+ { "TYPE_TV_TUNER", AudioDeviceType.Unknown }
77
+ };
78
+
79
+ internal event Action<string> onChanged;
80
+ internal event Action<string> onInterrupted;
81
+
82
+ private void OnAudioInterrupted(string param)
83
+ {
84
+ onInterrupted?.Invoke(param);
85
+ }
86
+
87
+ private void OnAudioDeviceAdded(string param)
88
+ {
89
+ if (string.IsNullOrEmpty(param))
90
+ return;
91
+ onChanged?.Invoke(param);
92
+ }
93
+
94
+ private void OnAudioDeviceRemoved(string param)
95
+ {
96
+ if (string.IsNullOrEmpty(param))
97
+ return;
98
+ onChanged?.Invoke(param);
99
+ }
100
+
101
+ private void OnAudioRouteChanged(string param)
102
+ {
103
+ onChanged?.Invoke(param);
104
+ }
105
+
106
+ internal void RegisterEvents()
107
+ {
108
+ #if !UNITY_EDITOR && UNITY_IOS
109
+ _RegisterAudioInfoChanged();
110
+ #elif !UNITY_EDITOR && UNITY_ANDROID
111
+ _detectorClass.CallStatic("registerEvents");
112
+ #endif
113
+ }
114
+
115
+ internal (AudioDeviceType AudioDeviceType, string RawType, string Name) GetInfo()
116
+ {
117
+ string param = string.Empty;
118
+ #if !UNITY_EDITOR && UNITY_IOS
119
+ param = _GetAudioInfo();
120
+ #elif !UNITY_EDITOR && UNITY_ANDROID
121
+ param = _detectorClass.CallStatic<string>("getAudioInfo");
122
+ #endif
123
+ return ParseStringInfo(param);
124
+ }
125
+
126
+ internal string GetCurrentRouteInputs()
127
+ {
128
+ #if !UNITY_EDITOR && UNITY_IOS
129
+ return _GetCurrentRouteInputs();
130
+ #else
131
+ return string.Empty;
132
+ #endif
133
+ }
134
+
135
+ internal (AudioDeviceType AudioDeviceType, string RawType, string Name) ParseStringInfo(string param)
136
+ {
137
+ if (string.IsNullOrEmpty(param))
138
+ return (AudioDeviceType.Unknown, null, null);
139
+
140
+ string[] parameters = param.Split(';');
141
+
142
+ if (parameters.Length < 2)
143
+ return (AudioDeviceType.Unknown, null, null);
144
+
145
+ string name = RemoveSurrogatePairs(parameters[0]);
146
+ string rawType = parameters[1];
147
+ AudioDeviceType type = MapDeviceType(rawType);
148
+ if (type == AudioDeviceType.Internal)
149
+ {
150
+ name = string.Empty;
151
+ }
152
+
153
+ return (type, rawType, name);
154
+ }
155
+
156
+ private AudioDeviceType MapDeviceType(string rawType)
157
+ {
158
+ return deviceTypeMapping.GetValueOrDefault(rawType, AudioDeviceType.Unknown);
159
+ }
160
+
161
+ private static string RemoveSurrogatePairs(string str, string replacementCharacter = "?")
162
+ {
163
+ if (str == null)
164
+ {
165
+ return null;
166
+ }
167
+
168
+ StringBuilder sb = null;
169
+
170
+ for (int i = 0; i < str.Length; i++)
171
+ {
172
+ char ch = str[i];
173
+
174
+ if (char.IsSurrogate(ch))
175
+ {
176
+ sb ??= new StringBuilder(str, 0, i, str.Length);
177
+
178
+ sb.Append(replacementCharacter);
179
+
180
+ // If there is a high+low surrogate, skip the low surrogate
181
+ if (i + 1 < str.Length && char.IsHighSurrogate(ch) && char.IsLowSurrogate(str[i + 1]))
182
+ {
183
+ i++;
184
+ }
185
+ }
186
+ else if (sb != null)
187
+ {
188
+ sb.Append(ch);
189
+ }
190
+ }
191
+
192
+ return sb == null ? str : sb.ToString();
193
+ }
194
+ }
195
+
196
+ internal enum AudioDeviceType
197
+ {
198
+ Unknown = 0,
199
+ Internal,
200
+ Wire,
201
+ Wireless,
202
+ Bluetooth,
203
+ }
204
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: ae405c9800a2487bb39ade689828e18d
3
+ timeCreated: 1717149554