Compare commits
2 Commits
59f5d747b4
...
319eb5eed9
| Author | SHA1 | Date | |
|---|---|---|---|
| 319eb5eed9 | |||
| 139eee8bd1 |
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user