Connect up the speech forwarder to the new UI.

This commit is contained in:
Jeremy Rand 2022-01-11 23:30:41 -05:00
parent c5e6cc70a5
commit dc3db26243
5 changed files with 46 additions and 81 deletions

View File

@ -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 = "<group>"; };
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 = "<group>"; };
9D5155F426A1EF7B0075EBC7 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
9D5155F626A1EF7C0075EBC7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
9D5155F926A1EF7C0075EBC7 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
9D5155FB26A1EF7C0075EBC7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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()
}
}

View File

@ -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()

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>329</string>
<string>358</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSRequiresIPhoneOS</key>

View File

@ -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("<hh\(stringToSend.count)s", [LISTEN_TEXT_MSG, stringToSend.count, stringToSend]))) {
case .success:
self.textHeard = latestText
logEvent(message: "Sent \"" + stringToSend + "\"")
logger.debug("Sent text \"\(stringToSend)\"")
break
case .failure(let error):
self.listening = false
logError(message: String(describing: error))
logger.error("Failed to send text: \(String(describing: error))")
}
}
}
@ -200,9 +201,14 @@ class SpeechForwarder : ObservableObject {
self.recognitionRequest = nil
self.recognitionTask = nil
self.listening = false
self.logEvent(message: "Listening stopped")
self.logger.debug("Stopped listening")
guard let client = self.client else { return }
client.send(data: self.isListening())
switch (client.send(data: self.isListening())) {
case .success:
break
case .failure(let error):
self.logger.error("Failed to send header: \(String(describing: error))")
}
}
}