M2-PT-DRP/source/Server.cpp

118 lines
2.8 KiB
C++

#include "Server.hpp"
#include <iostream>
#include <cstdint>
#include <mpg123.h>
#include <netdb.h>
#include <stdexcept>
#include <thread>
#include <sys/socket.h>
#include <vector>
Server::Server() {
// create a new mpg123 handle
int error;
this->mpgHandle = mpg123_new(nullptr, &error);
// open the mp3 file
if (mpg123_open(
this->mpgHandle,
"./assets/Caravan Palace - Wonderland.mp3"
))
throw std::runtime_error("Could not open file.");
// get the format of the file
if (mpg123_getformat(
this->mpgHandle,
&this->rate,
&this->channels,
&this->encoding
) != MPG123_OK)
throw std::runtime_error("Could not get the format of the file.");
}
Server::~Server() {
// delete the mpg123 handle
mpg123_close(this->mpgHandle);
mpg123_delete(this->mpgHandle);
}
void Server::loop() {
int error;
// create the socket
const int serverSocket = socket(
AF_INET6,
SOCK_DGRAM,
0
);
if (serverSocket < 0)
throw std::runtime_error("Could not create the socket.");
// get the broadcast address
addrinfo clientHints = {};
clientHints.ai_family = AF_INET6;
clientHints.ai_socktype = SOCK_DGRAM;
clientHints.ai_protocol = IPPROTO_UDP;
// TODO(Faraphel): ip / port as argument
addrinfo *clientInfo;
if((error = getaddrinfo(
"localhost",
// "ff02::1", // IPv6 local broadcast
"5650", // our port
&clientHints,
&clientInfo
)) != 0)
throw std::runtime_error("Could not get the address.\n" + std::string(gai_strerror(error)));
// read the file
std::vector<std::uint8_t> buffer(4096);
std::size_t done;
while (mpg123_read(
this->mpgHandle,
buffer.data(),
buffer.size(),
&done) == MPG123_OK
) {
// send the content of the file
sendto(
serverSocket,
buffer.data(),
buffer.size(),
0,
clientInfo->ai_addr,
clientInfo->ai_addrlen
);
std::cout << "[Server] sent : " << done << " bytes" << std::endl;
// wait 10ms to simulate lag
// TODO(Faraphel): should be extended to simulate live music streaming
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<uint64_t>(
(1 / static_cast<double>(this->rate * this->channels * mpg123_encsize(this->encoding))) *
1000 *
static_cast<double>(done)
)));
}
// free the server address
freeaddrinfo(clientInfo);
}
long Server::getRate() const {
return this->rate;
}
int Server::getChannels() const {
return this->channels;
}
int Server::getEncoding() const {
return this->encoding;
}