@siteed/audio-studio 3.0.3 → 3.0.4

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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
 
11
+ ## [3.0.4] - 2026-04-25
12
+ ### Changed
13
+ - fix(audio-studio): move module ops off main thread + fix iOS stop crash (#363) ([1a07d2d](https://github.com/deeeed/audiolab/commit/1a07d2d9222bfac1083b00d6de992fcb2a3be42d))
14
+ - chore(audio-studio): release @siteed/audio-studio@3.0.3 ([9d4d14e](https://github.com/deeeed/audiolab/commit/9d4d14e8dffd4378a71f2d3dfb5d7140b8248c0f))
15
+ - fix(audio-studio): convert trim ranges from Double to Long on Android (#347) (#360) ([6099e0e](https://github.com/deeeed/audiolab/commit/6099e0e81f3c8d7b1c109b415ad63e924f3f043b))
16
+ - feat(audio-studio): web trimAudio, WASM refactor, new utilities (#344) ([3d4862a](https://github.com/deeeed/audiolab/commit/3d4862a57a5eb2496169d27f758d7628d7d3659a))
17
+ - feat(sherpa-voice): comprehensive logging + fix Android prod model extraction (#342) ([5b20594](https://github.com/deeeed/audiolab/commit/5b20594c729a9deb703cbc2e23c07daa616149ab))
18
+ - fix(audio-studio): remove blocking CDN poll from publish.sh, sync wasmConfig to 3.0.2 ([290409a](https://github.com/deeeed/audiolab/commit/290409aae8d1160e1952a5ee1961ce3864fbb0c8))
19
+ - chore(audio-studio): release @siteed/audio-studio@3.0.2 ([ebd3300](https://github.com/deeeed/audiolab/commit/ebd330098d2756e6d5a555126e2dfc3fb038d155))
11
20
  ## [3.0.3] - 2026-04-12
12
21
  ### Changed
13
22
  - fix(audio-studio): convert trim ranges from Double to Long on Android (#347) (#360) ([6099e0e](https://github.com/deeeed/audiolab/commit/6099e0e81f3c8d7b1c109b415ad63e924f3f043b))
@@ -335,7 +344,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
335
344
  - Audio features extraction during recording
336
345
  - Consistent WAV PCM recording format across all platforms
337
346
 
338
- [unreleased]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.3...HEAD
347
+ [unreleased]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.4...HEAD
348
+ [3.0.4]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.3...@siteed/audio-studio@3.0.4
339
349
  [3.0.3]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.2...@siteed/audio-studio@3.0.3
340
350
  [3.0.2]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.2-beta.2...@siteed/audio-studio@3.0.2
341
351
  [3.0.1]: https://github.com/deeeed/audiolab/compare/@siteed/audio-studio@3.0.0...@siteed/audio-studio@3.0.1
@@ -455,49 +455,55 @@ class AudioRecorderManager(
455
455
  }
456
456
 
457
457
  private fun initializePhoneStateListener() {
458
- try {
459
- LogUtils.d(CLASS_NAME, "Initializing phone state listener...")
460
-
461
- if (permissionUtils.checkPhoneStatePermission()) {
462
- LogUtils.d(CLASS_NAME, "Phone state permission granted")
463
-
464
- val localTelephonyManager = telephonyManager
465
- if (localTelephonyManager != null) {
466
- try {
467
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
468
- // API 31+: Use modern TelephonyCallback which reliably fires on Android 12+
469
- val callback = object : TelephonyCallback(), TelephonyCallback.CallStateListener {
470
- override fun onCallStateChanged(state: Int) {
471
- handleCallStateChanged(state)
458
+ // The legacy PhoneStateListener (API < 31) requires a Looper on the
459
+ // thread that constructs it; calling listen() also expects the same.
460
+ // prepareRecording now runs on Dispatchers.IO (no Looper), so we
461
+ // marshal the whole registration to the main thread's Looper. The
462
+ // API 31+ path uses context.mainExecutor and is thread-safe, but we
463
+ // route everything through main for consistency.
464
+ android.os.Handler(android.os.Looper.getMainLooper()).post {
465
+ try {
466
+ LogUtils.d(CLASS_NAME, "Initializing phone state listener...")
467
+
468
+ if (permissionUtils.checkPhoneStatePermission()) {
469
+ LogUtils.d(CLASS_NAME, "Phone state permission granted")
470
+
471
+ val localTelephonyManager = telephonyManager
472
+ if (localTelephonyManager != null) {
473
+ try {
474
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
475
+ val callback = object : TelephonyCallback(), TelephonyCallback.CallStateListener {
476
+ override fun onCallStateChanged(state: Int) {
477
+ handleCallStateChanged(state)
478
+ }
472
479
  }
473
- }
474
- telephonyCallback = callback
475
- localTelephonyManager.registerTelephonyCallback(context.mainExecutor, callback)
476
- LogUtils.d(CLASS_NAME, "Successfully registered TelephonyCallback (API 31+)")
477
- } else {
478
- // Legacy: PhoneStateListener for API < 31
479
- phoneStateListener = object : PhoneStateListener() {
480
- @Deprecated("Deprecated in API 31")
481
- override fun onCallStateChanged(state: Int, phoneNumber: String?) {
482
- handleCallStateChanged(state)
480
+ telephonyCallback = callback
481
+ localTelephonyManager.registerTelephonyCallback(context.mainExecutor, callback)
482
+ LogUtils.d(CLASS_NAME, "Successfully registered TelephonyCallback (API 31+)")
483
+ } else {
484
+ phoneStateListener = object : PhoneStateListener() {
485
+ @Deprecated("Deprecated in API 31")
486
+ override fun onCallStateChanged(state: Int, phoneNumber: String?) {
487
+ handleCallStateChanged(state)
488
+ }
483
489
  }
490
+ localTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
491
+ LogUtils.d(CLASS_NAME, "Successfully registered PhoneStateListener (legacy)")
484
492
  }
485
- localTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
486
- LogUtils.d(CLASS_NAME, "Successfully registered PhoneStateListener (legacy)")
493
+ } catch (e: SecurityException) {
494
+ LogUtils.w(CLASS_NAME, "Missing permission for phone state listener: ${e.message}")
495
+ } catch (e: Exception) {
496
+ LogUtils.e(CLASS_NAME, "Failed to register phone state listener", e)
487
497
  }
488
- } catch (e: SecurityException) {
489
- LogUtils.w(CLASS_NAME, "Missing permission for phone state listener: ${e.message}")
490
- } catch (e: Exception) {
491
- LogUtils.e(CLASS_NAME, "Failed to register phone state listener", e)
498
+ } else {
499
+ LogUtils.w(CLASS_NAME, "TelephonyManager is null, phone call interruption handling disabled (device may not have telephony service)")
492
500
  }
493
501
  } else {
494
- LogUtils.w(CLASS_NAME, "TelephonyManager is null, phone call interruption handling disabled (device may not have telephony service)")
502
+ LogUtils.w(CLASS_NAME, "READ_PHONE_STATE permission not granted, phone call interruption handling disabled")
495
503
  }
496
- } else {
497
- LogUtils.w(CLASS_NAME, "READ_PHONE_STATE permission not granted, phone call interruption handling disabled")
504
+ } catch (e: Exception) {
505
+ LogUtils.e(CLASS_NAME, "Failed to initialize phone state listener", e)
498
506
  }
499
- } catch (e: Exception) {
500
- LogUtils.e(CLASS_NAME, "Failed to initialize phone state listener", e)
501
507
  }
502
508
  }
503
509