Update PDAB
- Added standard debugger file for logging - Added fault handler to see what happens if it faults
This commit is contained in:
@@ -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
28
debugger.py
Normal 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
61
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...")
|
||||
|
||||
Reference in New Issue
Block a user