#include "ServerTask.hpp" #include #include #include #include #include #include #include #include #include #include "../../packets/audio/AudioPacketData.hpp" #include "../../utils/audio.hpp" namespace drp::task { ServerTask::ServerTask() { this->channels = 0; this->encoding = 0; this->sampleRate = 0; // create a new mpg123 handle int error; this->mpgHandle = mpg123_new(nullptr, &error); if (this->mpgHandle == nullptr) throw std::runtime_error("[Server] Could not create a mpg123 handle."); // open the mp3 file // TODO(Faraphel): mp3 file as argument if (mpg123_open( this->mpgHandle, "./assets/Queen - Another One Bites the Dust.mp3" ) != MPG123_OK) throw std::runtime_error("[Server] Could not open file."); // get the format of the file if (mpg123_getformat( this->mpgHandle, &this->sampleRate, &this->channels, &this->encoding ) != MPG123_OK) throw std::runtime_error("[Server] Could not get the format of the file."); } ServerTask::~ServerTask() { // delete the mpg123 handle mpg123_close(this->mpgHandle); mpg123_delete(this->mpgHandle); } void ServerTask::handle(Context& context) { // TODO(Faraphel): create a chrony server // read the file packet::AudioPacketData audioPacket; std::size_t done; if (mpg123_read( this->mpgHandle, &audioPacket.content, std::size(audioPacket.content), &done ) != MPG123_OK) { std::cerr << "[Server] Could not read audio data from file." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); return; } // set the target time // TODO(Faraphel): dynamically change this delay to be the lowest possible audioPacket.timePlay = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(5000); // set the audio settings audioPacket.channels = this->channels; audioPacket.sampleFormat = util::encoding_mpg123_to_PulseAudio(this->encoding); audioPacket.sampleRate = this->sampleRate; // set the size of the content audioPacket.contentSize = done; // broadcast the audio data if (sendto( context.socket, &audioPacket, sizeof(audioPacket), 0, context.broadcastAddressInfo->ai_addr, context.broadcastAddressInfo->ai_addrlen ) == -1) { std::cerr << "[Server] Could not send audio packet: " << strerror(errno) << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); return; } std::cout << "[Server] Sent: " << done << " bytes" << std::endl; // wait for the duration of the audio chunk std::this_thread::sleep_for(std::chrono::milliseconds(static_cast( (1 / static_cast(this->sampleRate * this->channels * mpg123_encsize(this->encoding))) * 1000 * static_cast(done) ))); } }