diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 405db5f799..2b7afb9977 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -959,20 +959,21 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol case .failure(let error): switch error { case .audioRecorderError(.recordPermissionNotGranted): + MXLog.info("permission to record audio has not been granted.") state.bindings.confirmationAlertInfo = .init(id: .init(), title: L10n.dialogPermissionMicrophoneTitleIos(InfoPlistReader.main.bundleDisplayName), message: L10n.dialogPermissionMicrophoneDescriptionIos, primaryButton: .init(title: L10n.commonSettings, action: { [weak self] in self?.openSystemSettings() }), secondaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil)) default: - MXLog.error("failed to start voice message recording: \(error)") + MXLog.error("failed to start voice message recording. \(error)") } } } private func stopRecordingVoiceMessage() async { if case .failure(let error) = await voiceMessageRecorder.stopRecording() { - MXLog.error("failed to stop the recording", context: error) + MXLog.error("failed to stop the recording. \(error)") return } @@ -1012,7 +1013,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol case .success: await deleteCurrentVoiceMessage() case .failure(let error): - MXLog.error("failed to send the voice message", context: error) + MXLog.error("failed to send the voice message. \(error)") actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: false)))) displayError(.alert(L10n.errorFailedUploadingVoiceMessage)) } @@ -1020,7 +1021,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private func startPlayingRecordedVoiceMessage() async { if case .failure(let error) = await voiceMessageRecorder.startPlayback() { - MXLog.error("failed to play recorded voice message", context: error) + MXLog.error("failed to play recorded voice message. \(error)") } } diff --git a/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift b/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift index 90a851e679..8004928626 100644 --- a/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift +++ b/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift @@ -144,14 +144,19 @@ class AudioRecorder: NSObject, AudioRecorderProtocol, AVAudioRecorderDelegate { try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default) try AVAudioSession.sharedInstance().setActive(true) let url = URL.temporaryDirectory.appendingPathComponent("voice-message-\(recordID.identifier).m4a") - audioRecorder = try AVAudioRecorder(url: url, settings: settings) - audioRecorder?.delegate = self - audioRecorder?.isMeteringEnabled = true - audioRecorder?.record() - completion(.success(())) + let audioRecorder = try AVAudioRecorder(url: url, settings: settings) + audioRecorder.delegate = self + audioRecorder.isMeteringEnabled = true + if audioRecorder.record() { + self.audioRecorder = audioRecorder + completion(.success(())) + } else { + MXLog.error("audio recording failed to start") + completion(.failure(.recordingFailed)) + } } catch { - MXLog.error("audio recording failed: \(error)") - completion(.failure(.genericError)) + MXLog.error("audio recording failed to start. \(error)") + completion(.failure(.internalError(error: error))) } } } @@ -187,12 +192,14 @@ class AudioRecorder: NSObject, AudioRecorderProtocol, AVAudioRecorderDelegate { if success { actionsSubject.send(.didStopRecording) } else { + MXLog.error("audio recorder did finish recording with an error.") actionsSubject.send(.didFailWithError(error: AudioRecorderError.genericError)) } } func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) { try? AVAudioSession.sharedInstance().setActive(false) + MXLog.error("audio recorder encode error did occur. \(error?.localizedDescription ?? "")") actionsSubject.send(.didFailWithError(error: error ?? AudioRecorderError.genericError)) } diff --git a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift index 13c1714d6c..f41f8114fd 100644 --- a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift +++ b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift @@ -32,7 +32,9 @@ extension AudioRecordingIdentifier { enum AudioRecorderError: Error { case genericError + case internalError(error: Error) case recordPermissionNotGranted + case recordingFailed case recordingCancelled } diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift index 75fbbca4e3..ba47cda4e7 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift @@ -35,7 +35,7 @@ class VoiceMessageCache: VoiceMessageCacheProtocol { do { try cacheFile(source: fileURL, destination: url, move: move) } catch { - MXLog.error("Failed storing file in cache", context: error) + MXLog.error("Failed storing file in cache. \(error)") return .failure(.failedStoringFileInCache) } return .success(url) @@ -46,7 +46,7 @@ class VoiceMessageCache: VoiceMessageCacheProtocol { do { try FileManager.default.removeItem(at: temporaryFilesFolderURL) } catch { - MXLog.error("Failed clearing cached disk files", context: error) + MXLog.error("Failed clearing cached disk files. \(error)") } } } diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift index 7731fe6b15..cbeecd0a5a 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift @@ -130,7 +130,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { // linearly normalized to [0, 1] (1 -> -50 dB) waveformData = samples.map { UInt16(max(0, (1 - $0) * 1024)) } } catch { - MXLog.error("Waveform analysis failed: \(error)") + MXLog.error("Waveform analysis failed. \(error)") } return .success(waveformData) } @@ -154,7 +154,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { do { size = try UInt64(FileManager.default.sizeForItem(at: oggFile)) } catch { - MXLog.error("Failed to get the recording file size", context: error) + MXLog.error("Failed to get the recording file size. \(error)") return .failure(.failedSendingVoiceMessage) } let audioInfo = AudioInfo(duration: recordingDuration, size: size, mimetype: "audio/ogg") @@ -170,7 +170,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { try? FileManager.default.removeItem(at: oggFile) if case .failure(let error) = result { - MXLog.error("Failed to send the voice message.", context: error) + MXLog.error("Failed to send the voice message. \(error)") return .failure(.failedSendingVoiceMessage) }