Update PDAB

- Added standard debugger file for logging
- Added fault handler to see what happens if it faults
This commit is contained in:
Logan Cusano
2024-04-28 03:17:08 -04:00
parent fc6c114473
commit 098dfc9a10
3 changed files with 85 additions and 60 deletions

View File

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

28
debugger.py Normal file
View File

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

61
main.py
View File

@@ -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...")