M2-PT-DRP/source/behaviors/roles/MasterRole.py

62 lines
2.2 KiB
Python

import os
from datetime import datetime, timedelta
import pause
import pydub
from source.behaviors.roles import base
from source.managers import Manager
from source.packets import AudioPacket
from source.utils.crypto.type import CipherType
class MasterRole(base.BaseRole):
"""
Role used when the machine is declared as the master.
It will be the machine responsible for emitting data that the others peers should play together.
"""
TARGET_SIZE: int = 60 * 1024 # set an upper bound because of the IPv6 maximum packet size.
def __init__(self, manager: "Manager"):
super().__init__(manager)
# generate a random secret key for AES communication
self.manager.communication.secret_key = os.urandom(32)
# prepare the audio file that will be streamed
self.audio = pydub.AudioSegment.from_file("../assets/Caravan Palace - Wonderland.mp3")
self.play_time = datetime.now()
def handle(self):
# TODO(Faraphel): check if another server is emitting sound in the network. Return to undefined if yes
# calculate the number of bytes per milliseconds in the audio
bytes_per_ms = self.audio.frame_rate * self.audio.sample_width * self.audio.channels / 1000
# calculate the required chunk duration to reach that size
chunk_duration = timedelta(milliseconds=self.TARGET_SIZE / bytes_per_ms)
# calculate the audio time
chunk_start_time = datetime.now() - self.play_time
chunk_end_time = chunk_start_time + chunk_duration
# get the music for that period
chunk = self.audio[
chunk_start_time.total_seconds() * 1000 :
chunk_end_time.total_seconds() * 1000
]
# broadcast it in the network
audio_packet = AudioPacket(
datetime.now() + timedelta(seconds=5), # play it in some seconds to let all the machines get the sample
chunk.channels,
chunk.frame_rate,
chunk.sample_width,
chunk.raw_data,
)
self.manager.communication.broadcast(audio_packet, CipherType.AES_CBC)
# wait for the audio to play
# TODO(Faraphel): should adapt to the compute time above
pause.until(self.play_time + chunk_end_time)