diff --git a/ListenerGS.xcodeproj/project.pbxproj b/ListenerGS.xcodeproj/project.pbxproj index 9ad7a0d..b48473b 100644 --- a/ListenerGS.xcodeproj/project.pbxproj +++ b/ListenerGS.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 9D5155F326A1EF7B0075EBC7 /* ListenerGSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5155F226A1EF7B0075EBC7 /* ListenerGSApp.swift */; }; - 9D5155F526A1EF7B0075EBC7 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5155F426A1EF7B0075EBC7 /* ContentView.swift */; }; 9D5155F726A1EF7C0075EBC7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D5155F626A1EF7C0075EBC7 /* Assets.xcassets */; }; 9D5155FA26A1EF7C0075EBC7 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D5155F926A1EF7C0075EBC7 /* Preview Assets.xcassets */; }; 9D51560526A1EF7C0075EBC7 /* ListenerGSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D51560426A1EF7C0075EBC7 /* ListenerGSTests.swift */; }; @@ -52,7 +51,6 @@ 9D0DC15826F2E47A007EB92D /* ListenerGS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ListenerGS.entitlements; sourceTree = ""; }; 9D5155EF26A1EF7B0075EBC7 /* ListenerGS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ListenerGS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9D5155F226A1EF7B0075EBC7 /* ListenerGSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListenerGSApp.swift; sourceTree = ""; }; - 9D5155F426A1EF7B0075EBC7 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 9D5155F626A1EF7C0075EBC7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9D5155F926A1EF7C0075EBC7 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 9D5155FB26A1EF7C0075EBC7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -142,7 +140,6 @@ 9DD67CEF2728F5B700243FC6 /* DestinationsView.swift */, 9DCCDACB271FB87100F311DF /* GSDestinations.swift */, 9DD8905F2772D3B20084A894 /* GSView.swift */, - 9D5155F426A1EF7B0075EBC7 /* ContentView.swift */, 9D6ED239271E6BD600D773CD /* SpeechForwarder.swift */, 9DD8905E27726C140084A894 /* ListenerGS Icon.pxm */, 9D51566326A36F530075EBC7 /* BinUtils */, @@ -375,7 +372,6 @@ 9D51565326A36B410075EBC7 /* yudpsocket.c in Sources */, 9DD890602772D3B20084A894 /* GSView.swift in Sources */, 9D51565226A36B410075EBC7 /* Result.swift in Sources */, - 9D5155F526A1EF7B0075EBC7 /* ContentView.swift in Sources */, 9D6ED23A271E6BD600D773CD /* SpeechForwarder.swift in Sources */, 9D5155F326A1EF7B0075EBC7 /* ListenerGSApp.swift in Sources */, 9D51566526A36F6D0075EBC7 /* BinUtils.swift in Sources */, diff --git a/ListenerGS/ContentView.swift b/ListenerGS/ContentView.swift deleted file mode 100644 index 2e6a6ee..0000000 --- a/ListenerGS/ContentView.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// ContentView.swift -// ListenerGS -// -// Created by Jeremy Rand on 2021-07-16. -// - -import SwiftUI -import Speech - -struct ContentView: View { - @StateObject private var speechForwarder = SpeechForwarder() - // private var destinations: GSDestinations - - var body: some View { - VStack { - TextField("IP Address", text: $speechForwarder.ipAddress) { isEditing in - speechForwarder.isEditing = isEditing - } onCommit: { - speechForwarder.validate(destination: speechForwarder.ipAddress) - } - .padding() - - ScrollView() { - Text(speechForwarder.log) - .multilineTextAlignment(.leading) - } - - Button("Listen") { - speechForwarder.listen() - } - .padding() - .background(speechForwarder.listening ? Color.red : Color.clear) - .foregroundColor(speechForwarder.listening ? .black : .blue) - .disabled(speechForwarder.listenEnabled == false) - .frame(maxWidth: .infinity) - .buttonStyle(PlainButtonStyle()) - } - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/ListenerGS/GSView.swift b/ListenerGS/GSView.swift index cf84a8b..b317c2e 100644 --- a/ListenerGS/GSView.swift +++ b/ListenerGS/GSView.swift @@ -43,19 +43,28 @@ private extension GSButtonStyle { struct GSView: View { private let ipAddress : String + @StateObject private var speechForwarder = SpeechForwarder() var body: some View { VStack { - Button("\(Image(systemName: "desktopcomputer.and.arrow.down")) Connect to \(ipAddress)") { - print("Clicked connect") + Button(speechForwarder.connected ? + "\(Image(systemName: "desktopcomputer.trianglebadge.exclamationmark")) Disconnect from \(ipAddress)" : + "\(Image(systemName: "desktopcomputer.and.arrow.down")) Connect to \(ipAddress)") { + if (speechForwarder.connected) { + speechForwarder.disconnect() + } else { + speechForwarder.connect(destination: ipAddress) + } } .disabled(false) .buttonStyle(GSButtonStyle()) - Button("\(Image(systemName: "ear.and.waveform")) Listen and Send Text") { - print("Clicked listen") + Button(speechForwarder.listening ? + "\(Image(systemName: "ear.trianglebadge.exclamationmark")) Stop Listening" : + "\(Image(systemName: "ear.and.waveform")) Listen and Send Text") { + speechForwarder.listen() } - .disabled(true) + .disabled(!speechForwarder.connected) .buttonStyle(GSButtonStyle()) Spacer() diff --git a/ListenerGS/Info.plist b/ListenerGS/Info.plist index ee6c4f5..0ae7f72 100644 --- a/ListenerGS/Info.plist +++ b/ListenerGS/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 329 + 358 LSApplicationCategoryType public.app-category.utilities LSRequiresIPhoneOS diff --git a/ListenerGS/SpeechForwarder.swift b/ListenerGS/SpeechForwarder.swift index ec69ab3..0807c9b 100644 --- a/ListenerGS/SpeechForwarder.swift +++ b/ListenerGS/SpeechForwarder.swift @@ -6,16 +6,13 @@ // import Foundation - +import os import Speech class SpeechForwarder : ObservableObject { @Published var listening = false - @Published var listenEnabled = false - @Published var log = "" - @Published var ipAddress = "" + @Published var connected = false private var textHeard = "" - @Published var isEditing = false let LISTEN_STATE_MSG = 1 let LISTEN_TEXT_MSG = 2 @@ -31,30 +28,34 @@ class SpeechForwarder : ObservableObject { private let audioEngine = AVAudioEngine() - func logError(message: String) { - log.append("ERROR: " + message + "\n") - } + private let logger = Logger() - func logEvent(message: String) { - log.append("EVENT: " + message + "\n") - } - - func validate(destination : String) { - logEvent(message: "Attempting to connect to " + destination) + func connect(destination : String) { + logger.debug("Attempting to connect to \(destination)") client = TCPClient(address: destination, port: Int32(port)) guard let client = client else { return } switch client.connect(timeout: 10) { case .success: - listenEnabled = true - logEvent(message: "Connected to " + destination) + connected = true + logger.debug("Connected to \(destination)") case .failure(let error): client.close() self.client = nil - logError(message: String(describing: error)) + logger.error("Failed to connect to \(destination): \(String(describing: error))") break } } + func disconnect() { + if (listening) { + listen() + } + + guard let client = client else { return } + client.close() + connected = false + } + func listen() { self.listening.toggle() if (self.listening) { @@ -94,14 +95,14 @@ class SpeechForwarder : ObservableObject { break case .failure(let error): self.listening = false - logError(message: String(describing: error)) + logger.error("Unable to send header: \(String(describing: error))") } } if (self.listening) { do { try startRecording() - logEvent(message: "Listening...") + logger.debug("Started listening") } catch { self.listening = false @@ -109,7 +110,7 @@ class SpeechForwarder : ObservableObject { } if (!self.listening) { - logEvent(message: "Listening stopped") + logger.debug("Stopped listening") audioEngine.stop() recognitionRequest?.endAudio() switch (client.send(data: isListening())) { @@ -117,7 +118,7 @@ class SpeechForwarder : ObservableObject { break case .failure(let error): self.listening = false - logError(message: String(describing: error)) + logger.error("Failed to send header: \(String(describing: error))") } } } @@ -147,11 +148,11 @@ class SpeechForwarder : ObservableObject { switch (client.send(data: pack("