From 098dfc9a10678f1111c773dbcda92af58aed0a5a Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 28 Apr 2024 03:17:08 -0400 Subject: [PATCH] Update PDAB - Added standard debugger file for logging - Added fault handler to see what happens if it faults --- NoiseGatev2.py | 56 +++++++++++++++++++++++++-------------------- debugger.py | 28 +++++++++++++++++++++++ main.py | 61 +++++++++++++++++++++----------------------------- 3 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 debugger.py diff --git a/NoiseGatev2.py b/NoiseGatev2.py index 158937e..21bd513 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -6,10 +6,12 @@ import time import pyaudio import discord import numpy +from debugger import setup_logger voice_connection = None -LOGGER = logging.getLogger("Discord_Radio_Bot.NoiseGateV2") +# Configure logging +logger = setup_logger('NoiseGatev2') # noinspection PyUnresolvedReferences @@ -30,19 +32,19 @@ class AudioStream: if _input: self.paInstance_kwargs['input_device_index'] = _input_device_index else: - LOGGER.warning(f"[AudioStream.__init__]:\tInput was not enabled." + logger.warning(f"[AudioStream.__init__]:\tInput was not enabled." f" Reinitialize with '_input=True'") if _output_device_index: if _output: self.paInstance_kwargs['output_device_index'] = _output_device_index else: - LOGGER.warning(f"[AudioStream.__init__]:\tOutput was not enabled." + logger.warning(f"[AudioStream.__init__]:\tOutput was not enabled." f" Reinitialize with '_output=True'") if _init_on_startup: # Init PyAudio instance - LOGGER.info("Creating PyAudio instance") + logger.info("Creating PyAudio instance") self.paInstance = pyaudio.PyAudio() # Define and initialize stream object if we have been passed a device ID (pyaudio.open) @@ -50,27 +52,30 @@ class AudioStream: if _output_device_index or _input_device_index: if _init_on_startup: - LOGGER.info("Init stream") + logger.info("Init stream") self.init_stream() def init_stream(self, _new_output_device_index: int = None, _new_input_device_index: int = None): + logger.info("Checking what device has been set if any") # Check what device was asked to be changed (or set) if _new_input_device_index: if self.paInstance_kwargs['input']: self.paInstance_kwargs['input_device_index'] = _new_input_device_index else: - LOGGER.warning(f"[AudioStream.init_stream]:\tInput was not enabled when initialized." + logger.warning(f"[AudioStream.init_stream]:\tInput was not enabled when initialized." f" Reinitialize with '_input=True'") if _new_output_device_index: if self.paInstance_kwargs['output']: self.paInstance_kwargs['output_device_index'] = _new_output_device_index else: - LOGGER.warning(f"[AudioStream.init_stream]:\tOutput was not enabled when initialized." + logger.warning(f"[AudioStream.init_stream]:\tOutput was not enabled when initialized." f" Reinitialize with '_output=True'") + logger.info("Close the stream if it's open") self.close_if_open() + logger.info("Open the audio stream") # Open the stream self.stream = self.paInstance.open(**self.paInstance_kwargs) @@ -80,10 +85,10 @@ class AudioStream: if self.stream.is_active(): self.stream.stop_stream() self.stream.close() - LOGGER.debug(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") + logger.debug(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") def list_devices(self, _display_input_devices: bool = True, _display_output_devices: bool = True): - LOGGER.info('Getting a list of the devices connected') + logger.info('Getting a list of the devices connected') info = self.paInstance.get_host_api_info_by_index(0) numdevices = info.get('deviceCount') @@ -96,13 +101,13 @@ class AudioStream: input_device = self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name') devices['Input'][i] = input_device if _display_input_devices: - LOGGER.debug(f"Input Device id {i} - {input_device}") + logger.debug(f"Input Device id {i} - {input_device}") if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxOutputChannels')) > 0: output_device = self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name') devices['Output'][i] = output_device if _display_output_devices: - LOGGER.debug(f"Output Device id {i} - {output_device}") + logger.debug(f"Output Device id {i} - {output_device}") return devices @@ -126,28 +131,31 @@ class NoiseGate(AudioStream): def run(self) -> None: global voice_connection # Start the audio stream - LOGGER.debug(f"Starting stream") - self.stream.start_stream() - # Start the stream to discord - self.core() + logger.debug(f"Starting stream") + try: + self.stream.start_stream() + # Start the stream to discord + self.core() + except Exception as e: + logger.error(err) - def core(self, error=None): + def core(self, error=None): if error: - LOGGER.warning(error) + logger.warning(error) while not voice_connection.is_connected(): time.sleep(.2) if not voice_connection.is_playing(): - LOGGER.debug(f"Playing stream to discord") + logger.debug(f"Playing stream to discord") voice_connection.play(self.NGStream, after=self.core) async def close(self): - LOGGER.debug(f"Closing") + logger.debug(f"Closing") await voice_connection.disconnect() if self.stream.is_active: self.stream.stop_stream() - LOGGER.debug(f"Stopping stream") + logger.debug(f"Stopping stream") # noinspection PyUnresolvedReferences @@ -169,9 +177,9 @@ class NoiseGateStream(discord.AudioSource): if self.process_set_count % 10 == 0: if buffer_decibel >= self.stream.THRESHOLD: - LOGGER.debug(f"[Noisegate Open] {buffer_decibel} db") + logger.debug(f"[Noisegate Open] {buffer_decibel} db") else: - LOGGER.debug(f"[Noisegate Closed] {buffer_decibel} db") + logger.debug(f"[Noisegate Closed] {buffer_decibel} db") if buffer_decibel >= self.stream.THRESHOLD: self.NG_fadeout_count = self.NG_fadeout @@ -182,13 +190,13 @@ class NoiseGateStream(discord.AudioSource): else: if self.NG_fadeout_count > 0: self.NG_fadeout_count -= 1 - LOGGER.debug(f"Frames in fadeout remaining: {self.NG_fadeout_count}") + logger.debug(f"Frames in fadeout remaining: {self.NG_fadeout_count}") self.process_set_count += 1 if curr_buffer: return bytes(curr_buffer) except OSError as e: - LOGGER.warning(e) + logger.warning(e) pass def audio_datalist_set_volume(self, datalist, volume): diff --git a/debugger.py b/debugger.py new file mode 100644 index 0000000..cff39e1 --- /dev/null +++ b/debugger.py @@ -0,0 +1,28 @@ +import logging +import os + +running_dir = os.path.dirname(__file__) +# Ensure the directory exists +log_dir = f"{running_dir}/logs" +os.makedirs(log_dir, exist_ok=True) + + +def setup_logger(namespace): + # Create the file if it doesn't exist + log_file = f"{running_dir}/logs/pdab.log" + open(log_file, 'a').close() + + # Configure logging + logFormatter = logging.Formatter("%(asctime)s [%(threadName)-16.16s] [%(levelname)-7.7s] - %(message)s", "%Y-%m-%d %H:%M:%S") + logger = logging.getLogger(namespace) + logger.setLevel(logging.INFO) + + fileHandler = logging.FileHandler(log_file) + fileHandler.setFormatter(logFormatter) + logger.addHandler(fileHandler) + + consoleHandler = logging.StreamHandler() + consoleHandler.setFormatter(logFormatter) + logger.addHandler(consoleHandler) + + return logger \ No newline at end of file diff --git a/main.py b/main.py index fb9b35f..b5f435a 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,5 @@ # Python client file (client.py) import argparse -import logging import os import platform import socketio @@ -8,29 +7,11 @@ import asyncio from discord import Intents, opus from discord.ext import commands from NoiseGatev2 import NoiseGate +from debugger import setup_logger, running_dir +import faulthandler +faulthandler.enable() -running_dir = os.path.dirname(__file__) - -# Ensure the directory exists -log_dir = f"{running_dir}/logs" -os.makedirs(log_dir, exist_ok=True) - -# Create the file if it doesn't exist -log_file = f"{running_dir}/logs/pdab.log" -open(log_file, 'a').close() - -# Configure logging -logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s") -logger = logging.getLogger('main') -logger.setLevel(logging.INFO) - -fileHandler = logging.FileHandler(log_file) -fileHandler.setFormatter(logFormatter) -logger.addHandler(fileHandler) - -consoleHandler = logging.StreamHandler() -consoleHandler.setFormatter(logFormatter) -logger.addHandler(consoleHandler) +logger = setup_logger('main') # Example usage logger.info("Logging initialized successfully.") @@ -43,14 +24,19 @@ ng_threshold = None ### Core functions def load_opus(): + logger.info(f"Running dir: '{running_dir}'") processor = platform.machine() logger.info(f"Processor: {processor}") + logger.info(f'OS: {os.name}') - if os.name == 'nt': + if os.name == 'nt': opus_path = f'{running_dir}/opus/libopus_amd64.dll' if processor == "AMD64" else None else: opus_path = f'{running_dir}/opus/libopus_aarcch64.so' if processor == "aarch64" else f'{running_dir}/opus/libopus_armv7l.so' + logger.debug(f"Opus path: '{opus_path}'") + logger.info(f"Opus path: '{opus_path}'") + if opus_path: opus.load_opus(opus_path) logger.info(f"Loaded OPUS library from {opus_path}") @@ -85,6 +71,7 @@ async def join_voice_channel(channel_id): logging.error(e) logging.info('error encountered') + async def leave_voice_channel(guild_id): guild = await client.fetch_guild(guild_id) logger.info(f"Leaving voice channel in guild {guild}") @@ -198,19 +185,14 @@ async def on_ready(): logger.info("Loading OPUS library") load_opus() - if not opus.is_loaded(): - return + logger.info(opus.is_loaded()) - # Send update to socket server - try: + if opus.is_loaded(): logger.info('Emitting to the server') - await sio.emit('discord_ready', {'message': 'Discord bot is ready'}) - except Exception as e: - logger.error(f"Error emitting to the server: {e}") - logger.info('Server not ready yet') + await sio.emit('discord_ready', {'message': 'Discord bot is ready'}) -async def main(args): +async def start_bot(args): global client, device_id, ng_threshold # Connect to the WebSocket server @@ -241,6 +223,13 @@ def parse_arguments(): if __name__ == "__main__": - args = parse_arguments() - logger.info("Arguments: %s", args) - asyncio.run(main(args)) + try: + args = parse_arguments() + logger.info("Arguments: %s", args) + # Create an event loop + loop = asyncio.get_event_loop() + # Run the start_bot function within the event loop + loop.run_until_complete(start_bot(args)) + except Exception as e: + logger.error(e) + logger.warning("Exiting now...")