mirror of
https://github.com/jeremysrand/ListenerApp.git
synced 2024-06-06 09:29:29 +00:00
Connect up the speech forwarder to the new UI.
This commit is contained in:
parent
c5e6cc70a5
commit
dc3db26243
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
9D5155F326A1EF7B0075EBC7 /* ListenerGSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5155F226A1EF7B0075EBC7 /* ListenerGSApp.swift */; };
|
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 */; };
|
9D5155F726A1EF7C0075EBC7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D5155F626A1EF7C0075EBC7 /* Assets.xcassets */; };
|
||||||
9D5155FA26A1EF7C0075EBC7 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D5155F926A1EF7C0075EBC7 /* Preview 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 */; };
|
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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
9D5155FB26A1EF7C0075EBC7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
@ -142,7 +140,6 @@
|
||||||
9DD67CEF2728F5B700243FC6 /* DestinationsView.swift */,
|
9DD67CEF2728F5B700243FC6 /* DestinationsView.swift */,
|
||||||
9DCCDACB271FB87100F311DF /* GSDestinations.swift */,
|
9DCCDACB271FB87100F311DF /* GSDestinations.swift */,
|
||||||
9DD8905F2772D3B20084A894 /* GSView.swift */,
|
9DD8905F2772D3B20084A894 /* GSView.swift */,
|
||||||
9D5155F426A1EF7B0075EBC7 /* ContentView.swift */,
|
|
||||||
9D6ED239271E6BD600D773CD /* SpeechForwarder.swift */,
|
9D6ED239271E6BD600D773CD /* SpeechForwarder.swift */,
|
||||||
9DD8905E27726C140084A894 /* ListenerGS Icon.pxm */,
|
9DD8905E27726C140084A894 /* ListenerGS Icon.pxm */,
|
||||||
9D51566326A36F530075EBC7 /* BinUtils */,
|
9D51566326A36F530075EBC7 /* BinUtils */,
|
||||||
|
@ -375,7 +372,6 @@
|
||||||
9D51565326A36B410075EBC7 /* yudpsocket.c in Sources */,
|
9D51565326A36B410075EBC7 /* yudpsocket.c in Sources */,
|
||||||
9DD890602772D3B20084A894 /* GSView.swift in Sources */,
|
9DD890602772D3B20084A894 /* GSView.swift in Sources */,
|
||||||
9D51565226A36B410075EBC7 /* Result.swift in Sources */,
|
9D51565226A36B410075EBC7 /* Result.swift in Sources */,
|
||||||
9D5155F526A1EF7B0075EBC7 /* ContentView.swift in Sources */,
|
|
||||||
9D6ED23A271E6BD600D773CD /* SpeechForwarder.swift in Sources */,
|
9D6ED23A271E6BD600D773CD /* SpeechForwarder.swift in Sources */,
|
||||||
9D5155F326A1EF7B0075EBC7 /* ListenerGSApp.swift in Sources */,
|
9D5155F326A1EF7B0075EBC7 /* ListenerGSApp.swift in Sources */,
|
||||||
9D51566526A36F6D0075EBC7 /* BinUtils.swift in Sources */,
|
9D51566526A36F6D0075EBC7 /* BinUtils.swift in Sources */,
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,19 +43,28 @@ private extension GSButtonStyle {
|
||||||
|
|
||||||
struct GSView: View {
|
struct GSView: View {
|
||||||
private let ipAddress : String
|
private let ipAddress : String
|
||||||
|
@StateObject private var speechForwarder = SpeechForwarder()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Button("\(Image(systemName: "desktopcomputer.and.arrow.down")) Connect to \(ipAddress)") {
|
Button(speechForwarder.connected ?
|
||||||
print("Clicked connect")
|
"\(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)
|
.disabled(false)
|
||||||
.buttonStyle(GSButtonStyle())
|
.buttonStyle(GSButtonStyle())
|
||||||
|
|
||||||
Button("\(Image(systemName: "ear.and.waveform")) Listen and Send Text") {
|
Button(speechForwarder.listening ?
|
||||||
print("Clicked listen")
|
"\(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())
|
.buttonStyle(GSButtonStyle())
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>329</string>
|
<string>358</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.utilities</string>
|
<string>public.app-category.utilities</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|
|
@ -6,16 +6,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import os
|
||||||
import Speech
|
import Speech
|
||||||
|
|
||||||
class SpeechForwarder : ObservableObject {
|
class SpeechForwarder : ObservableObject {
|
||||||
@Published var listening = false
|
@Published var listening = false
|
||||||
@Published var listenEnabled = false
|
@Published var connected = false
|
||||||
@Published var log = ""
|
|
||||||
@Published var ipAddress = ""
|
|
||||||
private var textHeard = ""
|
private var textHeard = ""
|
||||||
@Published var isEditing = false
|
|
||||||
|
|
||||||
let LISTEN_STATE_MSG = 1
|
let LISTEN_STATE_MSG = 1
|
||||||
let LISTEN_TEXT_MSG = 2
|
let LISTEN_TEXT_MSG = 2
|
||||||
|
@ -31,30 +28,34 @@ class SpeechForwarder : ObservableObject {
|
||||||
|
|
||||||
private let audioEngine = AVAudioEngine()
|
private let audioEngine = AVAudioEngine()
|
||||||
|
|
||||||
func logError(message: String) {
|
private let logger = Logger()
|
||||||
log.append("ERROR: " + message + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func logEvent(message: String) {
|
func connect(destination : String) {
|
||||||
log.append("EVENT: " + message + "\n")
|
logger.debug("Attempting to connect to \(destination)")
|
||||||
}
|
|
||||||
|
|
||||||
func validate(destination : String) {
|
|
||||||
logEvent(message: "Attempting to connect to " + destination)
|
|
||||||
client = TCPClient(address: destination, port: Int32(port))
|
client = TCPClient(address: destination, port: Int32(port))
|
||||||
guard let client = client else { return }
|
guard let client = client else { return }
|
||||||
switch client.connect(timeout: 10) {
|
switch client.connect(timeout: 10) {
|
||||||
case .success:
|
case .success:
|
||||||
listenEnabled = true
|
connected = true
|
||||||
logEvent(message: "Connected to " + destination)
|
logger.debug("Connected to \(destination)")
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
client.close()
|
client.close()
|
||||||
self.client = nil
|
self.client = nil
|
||||||
logError(message: String(describing: error))
|
logger.error("Failed to connect to \(destination): \(String(describing: error))")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func disconnect() {
|
||||||
|
if (listening) {
|
||||||
|
listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let client = client else { return }
|
||||||
|
client.close()
|
||||||
|
connected = false
|
||||||
|
}
|
||||||
|
|
||||||
func listen() {
|
func listen() {
|
||||||
self.listening.toggle()
|
self.listening.toggle()
|
||||||
if (self.listening) {
|
if (self.listening) {
|
||||||
|
@ -94,14 +95,14 @@ class SpeechForwarder : ObservableObject {
|
||||||
break
|
break
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
self.listening = false
|
self.listening = false
|
||||||
logError(message: String(describing: error))
|
logger.error("Unable to send header: \(String(describing: error))")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.listening) {
|
if (self.listening) {
|
||||||
do {
|
do {
|
||||||
try startRecording()
|
try startRecording()
|
||||||
logEvent(message: "Listening...")
|
logger.debug("Started listening")
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
self.listening = false
|
self.listening = false
|
||||||
|
@ -109,7 +110,7 @@ class SpeechForwarder : ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.listening) {
|
if (!self.listening) {
|
||||||
logEvent(message: "Listening stopped")
|
logger.debug("Stopped listening")
|
||||||
audioEngine.stop()
|
audioEngine.stop()
|
||||||
recognitionRequest?.endAudio()
|
recognitionRequest?.endAudio()
|
||||||
switch (client.send(data: isListening())) {
|
switch (client.send(data: isListening())) {
|
||||||
|
@ -117,7 +118,7 @@ class SpeechForwarder : ObservableObject {
|
||||||
break
|
break
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
self.listening = false
|
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]))) {
|
switch (client.send(data: pack("<hh\(stringToSend.count)s", [LISTEN_TEXT_MSG, stringToSend.count, stringToSend]))) {
|
||||||
case .success:
|
case .success:
|
||||||
self.textHeard = latestText
|
self.textHeard = latestText
|
||||||
logEvent(message: "Sent \"" + stringToSend + "\"")
|
logger.debug("Sent text \"\(stringToSend)\"")
|
||||||
break
|
break
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
self.listening = false
|
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.recognitionRequest = nil
|
||||||
self.recognitionTask = nil
|
self.recognitionTask = nil
|
||||||
self.listening = false
|
self.listening = false
|
||||||
self.logEvent(message: "Listening stopped")
|
self.logger.debug("Stopped listening")
|
||||||
guard let client = self.client else { return }
|
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))")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user