Fix for recording
This commit is contained in:
parent
ac552c3749
commit
d95bbe51e2
@ -34,6 +34,7 @@
|
||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
|
||||
7A11474B23FF368B00B424AF /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474A23FF368B00B424AF /* Settings.swift */; };
|
||||
7A15051224DB3E3000F39631 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A15051124DB3E3000F39631 /* AnyEncodable.swift */; };
|
||||
7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A21112924FC3D7E003BBF6F /* AudioEngine.swift */; };
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADC6249D43210035F39E /* RegionsController.swift */; };
|
||||
7A27ADF3249F8B650035F39E /* RecordsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF2249F8B650035F39E /* RecordsController.swift */; };
|
||||
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */; };
|
||||
@ -116,6 +117,7 @@
|
||||
7A11474A23FF368B00B424AF /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
||||
7A15051124DB3E3000F39631 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
||||
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioEngine.swift; sourceTree = "<group>"; };
|
||||
7A27ADC6249D43210035F39E /* RegionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegionsController.swift; sourceTree = "<group>"; };
|
||||
7A27ADF2249F8B650035F39E /* RecordsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordsController.swift; sourceTree = "<group>"; };
|
||||
7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManagerExt.swift; sourceTree = "<group>"; };
|
||||
@ -320,6 +322,7 @@
|
||||
7A27ADF824A09CAD0035F39E /* CocoaError.swift */,
|
||||
7A659B5A24A3768A0043A0F2 /* Substrings.swift */,
|
||||
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */,
|
||||
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -547,6 +550,7 @@
|
||||
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
|
||||
7A488C3D24A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift in Sources */,
|
||||
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
|
||||
7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */,
|
||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */,
|
||||
7A488C3E24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift in Sources */,
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */,
|
||||
|
||||
@ -79,5 +79,21 @@
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "CFC2DD73-A257-45F3-A7A8-7D9462944F86"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AutoCat/Extensions/AudioEngine.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "12"
|
||||
endingLineNumber = "12"
|
||||
landmarkName = "setCategoryAsync(_:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
||||
@ -16,6 +16,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
var addButton: UIBarButtonItem!
|
||||
let bag = DisposeBag()
|
||||
var recordDisposable: Disposable?
|
||||
var audioSessionObserver: NSObjectProtocol?
|
||||
|
||||
let validLetters = ["А", "В", "Е", "К", "М", "Н", "О", "Р", "С", "Т", "У", "Х"]
|
||||
|
||||
@ -123,13 +124,26 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
.observeOn(MainScheduler.instance)
|
||||
.flatMap(self.makeStartSoundIfNeeded)
|
||||
.flatMap {
|
||||
DispatchQueue.main.async {
|
||||
alert = UIAlertController(title: "Recording...", message: nil, preferredStyle: .alert)
|
||||
alert!.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in self.recordDisposable?.dispose() }))
|
||||
alert!.addAction(UIAlertAction(title: "Done", style: .default, handler: { _ in self.recorder?.stopRecording() }))
|
||||
self.present(alert!, animated: true)
|
||||
}
|
||||
#if targetEnvironment(macCatalyst) || targetEnvironment(simulator)
|
||||
DispatchQueue.main.async {
|
||||
alert = self.showRecordingAlert()
|
||||
}
|
||||
#else
|
||||
if let observer = self.audioSessionObserver {
|
||||
NotificationCenter.default.removeObserver(observer, name: AVAudioSession.routeChangeNotification, object: nil)
|
||||
}
|
||||
self.audioSessionObserver = NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: nil, queue: .main) { notification in
|
||||
guard let dict = notification.userInfo as? [String: Any],
|
||||
let prev = dict["AVAudioSessionRouteChangePreviousRouteKey"] as? AVAudioSessionRouteDescription,
|
||||
let reasonInt = dict["AVAudioSessionRouteChangeReasonKey"] as? NSNumber,
|
||||
let reason = AVAudioSession.RouteChangeReason(rawValue: reasonInt.uintValue),
|
||||
let session = notification.object as? AVAudioSession else { return }
|
||||
|
||||
if reason == .categoryChange && session.category == .playAndRecord && prev.inputs.isEmpty && !session.currentRoute.inputs.isEmpty {
|
||||
alert = self.showRecordingAlert()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
let date = Date()
|
||||
let fileName = "recording-\(date.timeIntervalSince1970).m4a"
|
||||
url = try FileManager.default.url(for: fileName, in: "recordings")
|
||||
@ -160,6 +174,14 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func showRecordingAlert() -> UIAlertController {
|
||||
let alert = UIAlertController(title: "Recording...", message: nil, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in self.recordDisposable?.dispose() }))
|
||||
alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { _ in self.recorder?.stopRecording() }))
|
||||
self.present(alert, animated: true)
|
||||
return alert
|
||||
}
|
||||
|
||||
// MARK: - Processing
|
||||
|
||||
func getPlateNumber(from recognizedText: String) -> String? {
|
||||
|
||||
@ -61,7 +61,7 @@ class SettingsController: FormViewController {
|
||||
}
|
||||
}
|
||||
|
||||
+++ Section(footer: "When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri")
|
||||
+++ Section(footer: "When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri") { $0.tag = "BeepRecordSection" }
|
||||
<<< SwitchRow("BeepRecord") { row in
|
||||
row.title = "Beep before record"
|
||||
row.value = Settings.shared.recordBeep
|
||||
@ -75,6 +75,13 @@ class SettingsController: FormViewController {
|
||||
<<< ButtonRow("SignOut") { $0.title = "Sign Out" }.onCellSelection { cell, row in
|
||||
self.logout()
|
||||
}
|
||||
|
||||
#if targetEnvironment(macCatalyst)
|
||||
if let beepSection = self.form.sectionBy(tag: "BeepRecordSection") {
|
||||
beepSection.hidden = true
|
||||
beepSection.evaluateHidden()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
func logout() {
|
||||
|
||||
25
AutoCat/Extensions/AudioEngine.swift
Normal file
25
AutoCat/Extensions/AudioEngine.swift
Normal file
@ -0,0 +1,25 @@
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
import RxSwift
|
||||
|
||||
extension AVAudioSession {
|
||||
func setCategoryAsync(_ category: AVAudioSession.Category) -> Single<Void> {
|
||||
if self.category == category {
|
||||
return .just(())
|
||||
} else {
|
||||
return Single.create { observer in
|
||||
NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: self, queue: .main) { notification in
|
||||
print("")
|
||||
}
|
||||
|
||||
do {
|
||||
try self.setCategory(category, mode: .default, options: [])
|
||||
} catch {
|
||||
observer(.error(error))
|
||||
}
|
||||
|
||||
return Disposables.create()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,14 +72,14 @@ class LocationManager {
|
||||
private static func checkPermissions() -> Single<Void> {
|
||||
return Single<Void>.create { observer in
|
||||
switch CLLocationManager.authorizationStatus() {
|
||||
case .authorizedWhenInUse:
|
||||
case .authorizedWhenInUse, .authorizedAlways:
|
||||
observer(.success(()))
|
||||
break
|
||||
case .notDetermined:
|
||||
self.manager.requestWhenInUseAuthorization()
|
||||
let proxy = RxLocationManagerDelegateProxy.proxy(for: self.manager)
|
||||
_ = proxy.authSubject.skip(1).first().subscribe(onSuccess: { result in
|
||||
if let status = result, status == .authorizedWhenInUse {
|
||||
_ = proxy.authSubject.filter{ $0 != .notDetermined }.first().subscribe(onSuccess: { result in
|
||||
if let status = result, [.authorizedWhenInUse, .authorizedAlways].contains(status) {
|
||||
observer(.success(()))
|
||||
} else {
|
||||
observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"])))
|
||||
|
||||
@ -3,6 +3,7 @@ import Speech
|
||||
import AVFoundation
|
||||
import AudioToolbox
|
||||
import RxSwift
|
||||
import os.log
|
||||
|
||||
class Recorder {
|
||||
|
||||
@ -28,15 +29,7 @@ class Recorder {
|
||||
|
||||
func microphoneAvailable() -> Bool {
|
||||
// FIXME:
|
||||
// This is primarily for mac catalyst app.
|
||||
// On iOS this will always return true (as there is always at least one microphone on any iOS device)
|
||||
let session = AVAudioSession.sharedInstance()
|
||||
// #if targetEnvironment(macCatalyst)
|
||||
// for input in session.availableInputs! {
|
||||
// print(input.portType == .headsetMic)
|
||||
// }
|
||||
// #endif
|
||||
return session.availableInputs?.contains(where: { $0.portType == .builtInMic }) ?? false
|
||||
return true
|
||||
}
|
||||
|
||||
func requestPermissions() -> Single<Void> {
|
||||
@ -94,9 +87,6 @@ class Recorder {
|
||||
}
|
||||
|
||||
do {
|
||||
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
|
||||
try AVAudioSession.sharedInstance().setActive(true)
|
||||
|
||||
let inFormat = self.engine.inputNode.outputFormat(forBus: 0)
|
||||
ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, UInt32(MemoryLayout<AudioStreamBasicDescription>.size), inFormat.streamDescription)
|
||||
|
||||
@ -123,6 +113,9 @@ class Recorder {
|
||||
|
||||
self.engine.prepare()
|
||||
try self.engine.start()
|
||||
|
||||
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
|
||||
try AVAudioSession.sharedInstance().setActive(true)
|
||||
} catch {
|
||||
observer(.error(error))
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user