aes67-daemon/daemon/driver_manager.cpp
Andrea Bondavalli 259e99afbc First import
2020-01-28 20:16:30 +01:00

336 lines
10 KiB
C++

//
// driver_manager.cpp
//
// Copyright (c) 2019 2020 Andrea Bondavalli. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <thread>
#include "driver_manager.hpp"
#include "log.hpp"
static const std::vector<std::string> alsa_msg_str = {
"Start",
"Stop",
"Reset",
"StartIO",
"StopIO",
"SetSampleRate",
"GetSampleRate",
"GetAudioMode",
"SetDSDAudioMode",
"SetTICFrameSizeAt1FS",
"SetMaxTICFrameSize",
"SetNumberOfInputs",
"SetNumberOfOutputs",
"GetNumberOfInputs",
"GetNumberOfOutputs",
"SetInterfaceName",
"Add_RTPStream",
"Remove_RTPStream",
"Update_RTPStream_Name",
"GetPTPInfo",
"Hello",
"Bye",
"Ping",
"SetMasterOutputVolume",
"SetMasterOutputSwitch",
"GetMasterOutputVolume",
"GetMasterOutputSwitch",
"SetPlayoutDelay",
"SetCaptureDelay",
"GetRTPStreamStatus",
"SetPTPConfig",
"GetPTPConfig",
"GetPTPStatus"
};
static const std::vector<std::string> ptp_status_str = {
"unlocked",
"locking",
"locked"
};
std::shared_ptr<DriverManager> DriverManager::create() {
// no need to be thread-safe here
static std::weak_ptr<DriverManager> instance;
if (auto ptr = instance.lock()) {
return ptr;
}
auto ptr = std::shared_ptr<DriverManager>(new DriverManager());
instance = ptr;
return ptr;
}
bool DriverManager::init(const Config& config) {
if (!DriverHandler::init(config)) {
return false;
}
sample_rate = config.get_sample_rate();
TPTPConfig ptp_config;
ptp_config.ui8Domain = config.get_ptp_domain();
ptp_config.ui8DSCP = config.get_ptp_dscp();
bool res = hello() ||
start() ||
reset() ||
set_interface_name(config.get_interface_name()) ||
set_ptp_config(ptp_config) ||
set_tic_frame_size_at_1fs(config.get_tic_frame_size_at_1fs()) ||
set_playout_delay(config.get_playout_delay()) ||
set_max_tic_frame_size(config.get_max_tic_frame_size());
return !res;
}
bool DriverManager::terminate() {
stop();
bye();
return DriverHandler::terminate();
}
std::error_code DriverManager::hello() {
this->send_command(MT_ALSA_Msg_Hello, 0, nullptr);
return retcode_;
}
std::error_code DriverManager::bye() {
this->send_command(MT_ALSA_Msg_Bye, 0, nullptr);
return retcode_;
}
std::error_code DriverManager::start() {
this->send_command(MT_ALSA_Msg_Start, 0, nullptr);
return retcode_;
}
std::error_code DriverManager::stop() {
this->send_command(MT_ALSA_Msg_Stop, 0, nullptr);
return retcode_;
}
std::error_code DriverManager::reset() {
this->send_command(MT_ALSA_Msg_Reset, 0, nullptr);
return retcode_;
}
std::error_code DriverManager::set_ptp_config(const TPTPConfig& config) {
BOOST_LOG_TRIVIAL(info) << "driver_manager:: setting PTP Domain "
<< (int)config.ui8Domain << " DSCP "
<< (int)config.ui8DSCP;
this->send_command(MT_ALSA_Msg_SetPTPConfig, sizeof(TPTPConfig),
reinterpret_cast<const uint8_t*>(&config));
return retcode_;
}
std::error_code DriverManager::get_ptp_config(TPTPConfig& config) {
this->send_command(MT_ALSA_Msg_GetPTPConfig);
if (!retcode_) {
memcpy(&config, recv_data_, sizeof(TPTPConfig));
BOOST_LOG_TRIVIAL(debug)
<< "driver_manager:: PTP Domain " << (int)config.ui8Domain << " DSCP "
<< (int)config.ui8DSCP;
}
return retcode_;
}
std::error_code DriverManager::get_ptp_status(TPTPStatus& status) {
this->send_command(MT_ALSA_Msg_GetPTPStatus);
if (!retcode_) {
memcpy(&status, recv_data_, sizeof(TPTPStatus));
BOOST_LOG_TRIVIAL(debug)
<< "driver_manager:: PTP Status "
<< ptp_status_str[status.nPTPLockStatus] << " GMID " << status.ui64GMID
<< " Jitter " << status.i32Jitter;
}
return retcode_;
}
std::error_code DriverManager::set_interface_name(const std::string& ifname) {
BOOST_LOG_TRIVIAL(info) << "driver_manager:: setting interface " << ifname;
this->send_command(MT_ALSA_Msg_SetInterfaceName, ifname.length() + 1,
reinterpret_cast<const uint8_t*>(ifname.c_str()));
return retcode_;
}
std::error_code DriverManager::add_rtp_stream(
const TRTP_stream_info& stream_info,
uint64_t& stream_handle) {
this->send_command(MT_ALSA_Msg_Add_RTPStream, sizeof(TRTP_stream_info),
reinterpret_cast<const uint8_t*>(&stream_info));
if (!retcode_) {
memcpy(&stream_handle, recv_data_, sizeof(stream_handle));
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: add RTP stream success handle " << stream_handle;
}
return retcode_;
}
std::error_code DriverManager::get_rtp_stream_status(
uint64_t stream_handle,
TRTP_stream_status& stream_status) {
this->send_command(MT_ALSA_Msg_GetRTPStreamStatus, sizeof(uint64_t),
reinterpret_cast<const uint8_t*>(&stream_handle));
if (!retcode_) {
memcpy(&stream_status, recv_data_, sizeof(stream_status));
}
return retcode_;
}
std::error_code DriverManager::remove_rtp_stream(uint64_t stream_handle) {
this->send_command(MT_ALSA_Msg_Remove_RTPStream, sizeof(uint64_t),
reinterpret_cast<const uint8_t*>(&stream_handle));
return retcode_;
}
std::error_code DriverManager::ping() {
this->send_command(MT_ALSA_Msg_Ping);
return retcode_;
}
std::error_code DriverManager::set_sample_rate(uint32_t sample_rate) {
this->send_command(MT_ALSA_Msg_SetSampleRate, sizeof(uint32_t),
reinterpret_cast<const uint8_t*>(&sample_rate));
return retcode_;
}
std::error_code DriverManager::set_tic_frame_size_at_1fs(uint64_t frame_size) {
this->send_command(MT_ALSA_Msg_SetTICFrameSizeAt1FS, sizeof(uint64_t),
reinterpret_cast<const uint8_t*>(&frame_size));
return retcode_;
}
std::error_code DriverManager::set_max_tic_frame_size(uint64_t frame_size) {
this->send_command(MT_ALSA_Msg_SetMaxTICFrameSize, sizeof(uint64_t),
reinterpret_cast<const uint8_t*>(&frame_size));
return retcode_;
}
std::error_code DriverManager::set_playout_delay(int32_t delay) {
this->send_command(MT_ALSA_Msg_SetPlayoutDelay, sizeof(uint32_t),
reinterpret_cast<const uint8_t*>(&delay));
return retcode_;
}
std::error_code DriverManager::get_sample_rate(uint32_t& sample_rate) {
this->send_command(MT_ALSA_Msg_GetSampleRate);
if (!retcode_) {
memcpy(&sample_rate, recv_data_, sizeof(uint32_t));
BOOST_LOG_TRIVIAL(info) << "driver_manager:: sample rate " << sample_rate;
}
return retcode_;
}
std::error_code DriverManager::get_number_of_inputs(int32_t& inputs) {
this->send_command(MT_ALSA_Msg_GetNumberOfInputs);
if (!retcode_) {
memcpy(&inputs, recv_data_, sizeof(uint32_t));
BOOST_LOG_TRIVIAL(info) << "driver_manager:: number of inputs " << inputs;
}
return retcode_;
}
std::error_code DriverManager::get_number_of_outputs(int32_t& outputs) {
this->send_command(MT_ALSA_Msg_GetNumberOfOutputs);
if (!retcode_) {
memcpy(&outputs, recv_data_, sizeof(uint32_t));
BOOST_LOG_TRIVIAL(info) << "driver_manager:: number of outputs " << outputs;
}
return retcode_;
}
void DriverManager::on_command_done(enum MT_ALSA_msg_id id,
size_t size,
const uint8_t* data) {
BOOST_LOG_TRIVIAL(info) << "driver_manager:: cmd " << alsa_msg_str[id]
<< " done data len " << size;
memcpy(recv_data_, data, size);
retcode_ = std::error_code{};
}
void DriverManager::on_command_error(enum MT_ALSA_msg_id id,
std::error_code error) {
BOOST_LOG_TRIVIAL(error) << "driver_manager:: cmd " << alsa_msg_str[id]
<< " failed with error " << error.message();
retcode_ = error;
}
void DriverManager::on_event(enum MT_ALSA_msg_id id,
size_t& resp_size,
uint8_t* resp,
size_t req_size,
const uint8_t* req) {
BOOST_LOG_TRIVIAL(debug) << "driver_manager:: event " << alsa_msg_str[id]
<< " data len " << req_size;
switch (id) {
case MT_ALSA_Msg_Hello:
resp_size = 0;
break;
case MT_ALSA_Msg_Bye:
resp_size = 0;
break;
case MT_ALSA_Msg_SetMasterOutputVolume:
if (req_size == sizeof(int32_t)) {
memcpy(&output_volume, req, req_size);
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: event SetMasterOutputVolume "
<< output_volume;
}
resp_size = 0;
break;
case MT_ALSA_Msg_SetMasterOutputSwitch:
if (req_size == sizeof(int32_t)) {
memcpy(&output_switch, req, req_size);
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: event SetMasterOutputSwitch "
<< output_switch;
}
resp_size = 0;
break;
case MT_ALSA_Msg_SetSampleRate:
if (req_size == sizeof(uint32_t)) {
memcpy(&sample_rate, req, req_size);
BOOST_LOG_TRIVIAL(info) << "driver_manager:: event SetSampleRate " << sample_rate;
}
resp_size = 0;
break;
case MT_ALSA_Msg_GetMasterOutputVolume:
resp_size = sizeof(int32_t);
memcpy(resp, &output_volume, resp_size);
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: event GetMasterOutputVolume " << output_volume;
break;
case MT_ALSA_Msg_GetMasterOutputSwitch:
resp_size = sizeof(int32_t);
memcpy(resp, &output_switch, resp_size);
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: event GetMasterOutputSwitch " << output_switch;
break;
default:
BOOST_LOG_TRIVIAL(error) << "driver_manager:: unknown event "
<< alsa_msg_str[id] << " data len " << req_size;
break;
}
}
void DriverManager::on_event_error(enum MT_ALSA_msg_id id,
std::error_code error) {
BOOST_LOG_TRIVIAL(error) << "driver_manager:: event " << alsa_msg_str[id]
<< " error " << error;
}