EXPERIMENT: Added more specific path locations for mac to see if this stops it erroring

This commit is contained in:
Andrew Ward
2024-05-02 13:40:22 +01:00
parent 476e1f8e9f
commit d45876fa8b

View File

@@ -1,4 +1,5 @@
import tkinter as tk
import platform
from tkinter import ttk, messagebox, simpledialog, Menu
import os
import pyaudio
@@ -6,6 +7,8 @@ import wave
import webbrowser
from openai import OpenAI
from dotenv import load_dotenv
from pathlib import Path
# Load environment variables
@@ -209,23 +212,63 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
def get_app_support_path_mac():
home = Path.home()
app_support_path = home / 'Library' / 'Application Support' / 'scorchsoft-text-to-mic'
app_support_path.mkdir(parents=True, exist_ok=True) # Ensure directory exists
return app_support_path
def save_api_key_mac(api_key):
env_path = get_app_support_path() / '.env'
with open(env_path, 'w') as f:
f.write(f"OPENAI_API_KEY={api_key}\n")
# Consider manually loading this .env file into your environment as needed
def load_api_key_mac():
env_path = get_app_support_path() / '.env'
if env_path.exists():
with open(env_path, 'r') as f:
for line in f:
if line.startswith('OPENAI_API_KEY'):
return line.strip().split('=')[1]
return None
def get_api_key(self):
# First, try to load the API key from environment variables or local file
api_key = os.getenv("OPENAI_API_KEY")
if not api_key: # No API key found in the environment
self.show_instructions() # Show the "How to Use" modal after setting the key
api_key = simpledialog.askstring("API Key", "Enter your OpenAI API Key:", parent=self)
if api_key:
self.save_api_key(api_key)
messagebox.showinfo("API Key Set", "The OpenAI API Key has been updated successfully.")
if not api_key: # Check for macOS and use the macOS-specific method
if platform.system() == 'Darwin': # Darwin is the system name for macOS
api_key = self.load_api_key_mac()
# If no API key is found, prompt the user
if not api_key:
self.show_instructions() # Show the "How to Use" modal after setting the key
api_key = simpledialog.askstring("API Key", "Enter your OpenAI API Key:", parent=self)
if api_key:
try:
if platform.system() == 'Darwin':
self.save_api_key_mac(api_key)
else:
self.save_api_key(api_key)
messagebox.showinfo("API Key Set", "The OpenAI API Key has been updated successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to save API key: {str(e)}")
return api_key
def save_api_key(self, api_key):
with open('.env', 'w') as f:
f.write(f"OPENAI_API_KEY={api_key}\n")
load_dotenv()
try:
if platform.system() == 'Darwin':
self.save_api_key_mac(api_key)
else:
with open('.env', 'w') as f:
f.write(f"OPENAI_API_KEY={api_key}\n")
load_dotenv() # Reload environment to include the new API key
except Exception as e:
messagebox.showerror("Error", f"Failed to save API key: {str(e)}")
def get_audio_devices(self):
p = pyaudio.PyAudio()
@@ -236,6 +279,13 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
devices[info['name']] = i
p.terminate()
return devices
def get_audio_file_path(self, filename):
if platform.system() == 'Darwin': # Check if the OS is macOS
return self.get_app_support_path_mac() / filename
else:
return Path(filename) # Default to current directory for non-macOS systems
def submit_text(self):
@@ -264,8 +314,9 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
input=text,
response_format='wav'
)
self.last_audio_file = "last_output.wav"
response.stream_to_file(self.last_audio_file)
self.last_audio_file = self.get_audio_file_path("last_output.wav")
response.stream_to_file(str(self.last_audio_file))
#Play to either two or a single stream
if primary_index and secondary_index != "None" and secondary_index is not None:
@@ -287,12 +338,30 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
try:
# Open all files and start all streams
for file_path, device_index in zip(file_paths, device_indices):
wf = wave.open(file_path, 'rb')
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
output_device_index=int(device_index))
try:
# Ensure the file_path is a string when opening the file
wf = wave.open(str(file_path), 'rb')
except FileNotFoundError:
messagebox.showerror("File Not Found", f"Could not find audio file: {file_path}")
continue # Skip this iteration and proceed with other files if any
except wave.Error as e:
messagebox.showerror("Wave Error", f"Error reading audio file: {file_path}. Error: {str(e)}")
continue
try:
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
output_device_index=int(device_index))
except Exception as e:
messagebox.showerror("Stream Creation Error", f"Failed to create audio stream for device index {device_index}: {str(e)}")
wf.close()
continue
streams.append((stream, wf))
# Play interleaved
@@ -308,6 +377,7 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
wf.close()
streams.remove((stream, wf))
active_streams -= 1
except Exception as e:
messagebox.showerror("Playback Error", f"Error during multiplexed playback: {e}")
finally:
@@ -316,8 +386,6 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
def play_last_audio(self):
if hasattr(self, 'last_audio_file'):
primary_index = self.available_devices.get(self.device_index.get(), None)
secondary_index = self.available_devices.get(self.device_index_2.get(), None) if self.device_index_2.get() != "None" else None