diff --git a/record/CHANGELOG.md b/record/CHANGELOG.md index cd85c317..7d7b12b8 100644 --- a/record/CHANGELOG.md +++ b/record/CHANGELOG.md @@ -1,3 +1,6 @@ +## 5.0.2 +* fix: Creation sequence which may lead to unexpected behaviours. + ## 5.0.1 * fix: close state stream controller on dispose. diff --git a/record/lib/src/record.dart b/record/lib/src/record.dart index 05bda636..0aea5e4b 100644 --- a/record/lib/src/record.dart +++ b/record/lib/src/record.dart @@ -19,30 +19,23 @@ class AudioRecorder { Timer? _amplitudeTimer; late Duration _amplitudeTimerInterval; + // Recorder ID final String _recorderId; + // Flag to create the recorder if needed with `_recorderId`. + bool? _created; - /// Completer to wait until the native player and its event stream are - /// created. - final _createCompleter = Completer(); + AudioRecorder() : _recorderId = _uuid.v4(); - AudioRecorder() : _recorderId = _uuid.v4() { - _create(); - } - - Future _create() async { - try { - await RecordPlatform.instance.create(_recorderId); + Future _create() async { + await RecordPlatform.instance.create(_recorderId); - final stream = RecordPlatform.instance.onStateChanged(_recorderId); - _stateStreamSubscription = stream.listen( - _stateStreamCtrl.add, - onError: _stateStreamCtrl.addError, - ); + final stream = RecordPlatform.instance.onStateChanged(_recorderId); + _stateStreamSubscription = stream.listen( + _stateStreamCtrl.add, + onError: _stateStreamCtrl.addError, + ); - _createCompleter.complete(); - } catch (e, stackTrace) { - _createCompleter.completeError(e, stackTrace); - } + return true; } /// Starts new recording session. @@ -55,7 +48,7 @@ class AudioRecorder { RecordConfig config, { required String path, }) async { - await _createCompleter.future; + _created ??= await _create(); await RecordPlatform.instance.start(_recorderId, config, path: path); @@ -67,7 +60,7 @@ class AudioRecorder { /// When stopping the record, you must rely on stream close event to get /// full recorded data. Future> startStream(RecordConfig config) async { - await _createCompleter.future; + _created ??= await _create(); await _stopRecordStream(); final stream = await RecordPlatform.instance.startStream( @@ -95,7 +88,7 @@ class AudioRecorder { /// /// Returns the output path if any. Future stop() async { - await _createCompleter.future; + _created ??= await _create(); _amplitudeTimer?.cancel(); final path = await RecordPlatform.instance.stop(_recorderId); @@ -107,14 +100,14 @@ class AudioRecorder { /// Pauses recording session. Future pause() async { - await _createCompleter.future; + _created ??= await _create(); _amplitudeTimer?.cancel(); return RecordPlatform.instance.pause(_recorderId); } /// Resumes recording session after [pause]. Future resume() async { - await _createCompleter.future; + _created ??= await _create(); _startAmplitudeTimer(); return RecordPlatform.instance.resume(_recorderId); } @@ -122,19 +115,19 @@ class AudioRecorder { /// Checks if there's valid recording session. /// So if session is paused, this method will still return [true]. Future isRecording() async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.isRecording(_recorderId); } /// Checks if recording session is paused. Future isPaused() async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.isPaused(_recorderId); } /// Checks and requests for audio record permission. Future hasPermission() async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.hasPermission(_recorderId); } @@ -145,20 +138,20 @@ class AudioRecorder { /// On web, and in general, you should already have permission before /// accessing this method otherwise the list may return an empty list. Future> listInputDevices() async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.listInputDevices(_recorderId); } /// Gets current average & max amplitudes (dBFS) /// Always returns zeros on unsupported platforms Future getAmplitude() async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.getAmplitude(_recorderId); } /// Checks if the given encoder is supported on the current platform. Future isEncoderSupported(AudioEncoder encoder) async { - await _createCompleter.future; + _created ??= await _create(); return RecordPlatform.instance.isEncoderSupported(_recorderId, encoder); } diff --git a/record/pubspec.yaml b/record/pubspec.yaml index 3ca10ce8..7237d89d 100644 --- a/record/pubspec.yaml +++ b/record/pubspec.yaml @@ -1,6 +1,6 @@ name: record -description: Audio recorder from microphone to a given file path with multiple codecs, bit rate and sampling rate options. -version: 5.0.1 +description: Audio recorder from microphone to file or stream with multiple codecs, bit rate and sampling rate options. +version: 5.0.2 homepage: https://github.com/llfbandit/record/tree/master/record environment: @@ -11,14 +11,15 @@ dependencies: flutter: sdk: flutter + # https://pub.dev/packages/uuid uuid: ">=3.0.7 <5.0.0" record_platform_interface: ^1.0.2 - record_web: ^1.0.0 - record_windows: ^1.0.0 + record_web: ^1.0.4 + record_windows: ^1.0.2 record_linux: '>=0.5.0 <1.0.0' - record_android: ^1.0.0 - record_darwin: ^1.0.0 + record_android: ^1.0.4 + record_darwin: ^1.0.1 dev_dependencies: # https://pub.dev/packages/flutter_lints diff --git a/record_windows/CHANGELOG.md b/record_windows/CHANGELOG.md index 4e9e1f3f..6022ad25 100644 --- a/record_windows/CHANGELOG.md +++ b/record_windows/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.0.2 +* fix: Quick creation/start/stop sequence resulting in a crash. + ## 1.0.1 * fix: UTF-16 to UTF-8 could fail. diff --git a/record_windows/pubspec.yaml b/record_windows/pubspec.yaml index d9f84305..a0cf8022 100644 --- a/record_windows/pubspec.yaml +++ b/record_windows/pubspec.yaml @@ -1,6 +1,6 @@ name: record_windows description: Windows specific implementation for record package called by record_platform_interface. -version: 1.0.1 +version: 1.0.2 homepage: https://github.com/llfbandit/record/tree/master/record_windows environment: diff --git a/record_windows/windows/record.cpp b/record_windows/windows/record.cpp index 76a27b7f..836cdb4e 100644 --- a/record_windows/windows/record.cpp +++ b/record_windows/windows/record.cpp @@ -245,6 +245,9 @@ namespace record_windows { HRESULT hr = S_OK; + // Release reader callback first + SafeRelease(m_pReader); + if (m_pSource) { hr = m_pSource->Stop(); @@ -282,7 +285,6 @@ namespace record_windows SafeRelease(m_pSource); SafeRelease(m_pPresentationDescriptor); - SafeRelease(m_pReader); SafeRelease(m_pWriter); SafeRelease(m_pMediaType); m_pConfig = nullptr; diff --git a/record_windows/windows/record_readercallback.cpp b/record_windows/windows/record_readercallback.cpp index 63b269b6..213c96c2 100644 --- a/record_windows/windows/record_readercallback.cpp +++ b/record_windows/windows/record_readercallback.cpp @@ -94,7 +94,7 @@ namespace record_windows else { // Reader error. - auto errorText = std::system_category().message(hr); + auto errorText = std::system_category().message(hrStatus); printf("Record: Error when reading sample (0x%X)\n%s\n", hrStatus, errorText.c_str()); Stop();