2 Commits

Author SHA1 Message Date
319eb5eed9 fix a typo 2025-02-24 09:02:33 +01:00
139eee8bd1 Improve the commandline ui 2025-02-24 09:01:29 +01:00
2 changed files with 60 additions and 11 deletions

View File

@@ -50,6 +50,49 @@ from bumble.audio import io as audio_io
import auracast_config
# modified from bumble
class ModWaveAudioInput(audio_io.ThreadedAudioInput):
"""Audio input that reads PCM samples from a .wav file."""
def __init__(self, filename: str) -> None:
super().__init__()
self._filename = filename
self._wav: wave.Wave_read | None = None
self._bytes_read = 0
self.rewind=True
def _open(self) -> audio_io.PcmFormat:
self._wav = wave.open(self._filename, 'rb')
if self._wav.getsampwidth() != 2:
raise ValueError('sample width not supported')
return audio_io.PcmFormat(
audio_io.PcmFormat.Endianness.LITTLE,
audio_io.PcmFormat.SampleType.INT16,
self._wav.getframerate(),
self._wav.getnchannels(),
)
def _read(self, frame_size: int) -> bytes:
if not self._wav:
return b''
pcm_samples = self._wav.readframes(frame_size)
if not pcm_samples and self._bytes_read:
if not self.rewind:
return None
# Loop around.
self._wav.rewind()
self._bytes_read = 0
pcm_samples = self._wav.readframes(frame_size)
self._bytes_read += len(pcm_samples)
return pcm_samples
def _close(self) -> None:
if self._wav:
self._wav.close()
audio_io.WaveAudioInput = ModWaveAudioInput
# -----------------------------------------------------------------------------
# Logging

View File

@@ -12,9 +12,15 @@ import multicast
import auracast_config
class Multicaster:
"""
A class responsible for managing the multicasting and audio streaming process.
It provides methods to initialize and shutdown the broadcasting, as well as start and stop the streaming.
The class also manages the underlying device and advertising sets.
"""
def __init__(
self,
global_conf: auracast_config.AuracastGlobalConfig,
self,
global_conf: auracast_config.AuracastGlobalConfig,
big_conf: List[auracast_config.AuracastBigConfig]
):
self.is_auracast_init = False
@@ -61,9 +67,14 @@ class Multicaster:
self.__init__(self.global_conf, self.big_conf)
async def shutdown(self):
await self.device.stop_advertising()
for big in self.bigs.values():
await big['advertising_set'].stop()
self.is_auracast_init = False
self. is_audio_init = False
if self.device:
await self.device.stop_advertising()
if self.bigs:
for big in self.bigs.values():
if big['advertising_set']:
await big['advertising_set'].stop()
await self.device_acm.__aexit__(None, None, None) # Manually triggering teardown
@@ -71,7 +82,7 @@ class Multicaster:
# example commandline ui
async def command_line_ui(caster: Multicaster):
while True:
command = await aioconsole.ainput("\nCommands: [start|stop|init|quit] > ")
command = await aioconsole.ainput("\nCommands: [start_audio|stop_audio|stop|init|init_audio|quit] > ")
if command.strip().lower() == "start_audio":
caster.start_streaming()
@@ -94,11 +105,6 @@ async def command_line_ui(caster: Multicaster):
elif command.strip().lower() == "init_audio":
await caster.init_audio()
#elif command.strip().lower().startswith("set "):
#_, new_message = command.split(" ", 1)
#multicaster.set_message(new_message)
#print(f"✏️ Message updated to: {new_message}")
elif command.strip().lower() == "quit":
print("👋 Exiting...")
if caster.device: