import threading
import soundcard as sc
import azure.cognitiveservices.speech as speechsdk
import queue
import warnings

# Suppress the SoundcardRuntimeWarning
warnings.filterwarnings("ignore", category=sc.SoundcardRuntimeWarning)

# Your Azure subscription key and region
audio_key = 'YOUR_AZURE_SUBSCRIPTION_KEY'
audio_region = 'YOUR_AZURE_REGION'

# Queue for passing audio data between threads
mic_queue = queue.Queue()
speaker_queue = queue.Queue()

# Function to capture microphone audio
def capture_mic_audio(mic_queue):
    mic = sc.get_microphone(id=str(sc.default_microphone().name))
    with mic.recorder(samplerate=48000) as mic_recorder:
        while True:
            data = mic_recorder.record(numframes=1024)
            mic_queue.put(data)

# Function to capture speaker audio
def capture_speaker_audio(speaker_queue):
    speaker = sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True)
    with speaker.recorder(samplerate=48000) as speaker_recorder:
        while True:
            data = speaker_recorder.record(numframes=1024)
            speaker_queue.put(data)

# Function to create an audio input stream for Azure Speech SDK
def create_audio_input_stream(audio_queue):
    class AudioInputStream(speechsdk.audio.PullAudioInputStreamCallback):
        def __init__(self):
            super().__init__()
        
        def read(self, buffer, size):
            try:
                data = audio_queue.get(block=False)
                buffer[:len(data)] = data
                return len(data)
            except queue.Empty:
                return 0

        def close(self):
            pass

    return speechsdk.audio.AudioConfig(stream=speechsdk.audio.PullAudioInputStream(AudioInputStream()))

# Function to start Azure speech recognition
def start_recognition(audio_config, speech_config, name):
    recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config, audio_config=audio_config)
    
    def recognized(evt):
        if evt.result.reason == speechsdk.ResultReason.RecognizedSpeech:
            print(f"{name} recognized: {evt.result.text}")
        elif evt.result.reason == speechsdk.ResultReason.NoMatch:
            print(f"{name} recognized: No speech could be recognized")
        elif evt.result.reason == speechsdk.ResultReason.Canceled:
            cancellation_details = evt.result.cancellation_details
            print(f"{name} recognized: Canceled: {cancellation_details.reason}")
            if cancellation_details.reason == speechsdk.CancellationReason.Error:
                print(f"Error details: {cancellation_details.error_details}")
    
    recognizer.recognized.connect(recognized)
    recognizer.start_continuous_recognition_async()
    return recognizer

# Main function
def main():
    speech_config = speechsdk.SpeechConfig(subscription=audio_key, region=audio_region)
    speech_config.speech_recognition_language = "en-US"

    # Start capturing audio
    threading.Thread(target=capture_mic_audio, args=(mic_queue,), daemon=True).start()
    threading.Thread(target=capture_speaker_audio, args=(speaker_queue,), daemon=True).start()

    # Create audio input streams
    mic_audio_input = create_audio_input_stream(mic_queue)
    speaker_audio_input = create_audio_input_stream(speaker_queue)

    # Start speech recognizers
    mic_recognizer = start_recognition(mic_audio_input, speech_config, "Microphone")
    speaker_recognizer = start_recognition(speaker_audio_input, speech_config, "Speaker")

    # Keep the program running to process transcriptions
    try:
        while True:
            pass
    except KeyboardInterrupt:
        mic_recognizer.stop_continuous_recognition_async()
        speaker_recognizer.stop_continuous_recognition_async()

if __name__ == "__main__":
    main()    CAN we do this without using api ....means can we do this with librraies