mirror of
https://github.com/badaix/snapcast.git
synced 2025-04-28 17:57:05 +02:00
Add code documentation
This commit is contained in:
parent
c2bebb4bae
commit
b773ccda18
9 changed files with 116 additions and 63 deletions
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Client: Add support for (secure-) websockets (Issue #1325)
|
- Client: Add support for (secure-) websockets (Issue #1325, PR #1340)
|
||||||
- Server: Add client authentication (Issue #1334)
|
- Server: Add client authentication (Issue #1334, PR #1340)
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,7 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_CLIENT_INFO_HPP
|
#pragma once
|
||||||
#define MESSAGE_CLIENT_INFO_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "json_message.hpp"
|
#include "json_message.hpp"
|
||||||
|
@ -27,39 +26,47 @@ namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Client information sent from client to server
|
/// Client information sent from client to server
|
||||||
/// Might also be used for sync stats and latency estimations
|
/// Might also be used for other things in future, like
|
||||||
|
/// - sync stats
|
||||||
|
/// - latency estimations
|
||||||
|
/// - Battery status
|
||||||
|
/// - ...
|
||||||
class ClientInfo : public JsonMessage
|
class ClientInfo : public JsonMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// c'tor
|
||||||
ClientInfo() : JsonMessage(message_type::kClientInfo)
|
ClientInfo() : JsonMessage(message_type::kClientInfo)
|
||||||
{
|
{
|
||||||
setVolume(100);
|
setVolume(100);
|
||||||
setMuted(false);
|
setMuted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~ClientInfo() override = default;
|
~ClientInfo() override = default;
|
||||||
|
|
||||||
|
/// @return the volume in percent
|
||||||
uint16_t getVolume()
|
uint16_t getVolume()
|
||||||
{
|
{
|
||||||
return get("volume", static_cast<uint16_t>(100));
|
return get("volume", static_cast<uint16_t>(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return if muted or not
|
||||||
bool isMuted()
|
bool isMuted()
|
||||||
{
|
{
|
||||||
return get("muted", false);
|
return get("muted", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the volume to @p volume percent
|
||||||
void setVolume(uint16_t volume)
|
void setVolume(uint16_t volume)
|
||||||
{
|
{
|
||||||
msg["volume"] = volume;
|
msg["volume"] = volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set muted to @p muted
|
||||||
void setMuted(bool muted)
|
void setMuted(bool muted)
|
||||||
{
|
{
|
||||||
msg["muted"] = muted;
|
msg["muted"] = muted;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_CODEC_HEADER_HPP
|
#pragma once
|
||||||
#define MESSAGE_CODEC_HEADER_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
@ -31,13 +31,15 @@ namespace msg
|
||||||
class CodecHeader : public BaseMessage
|
class CodecHeader : public BaseMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CodecHeader(const std::string& codecName = "", uint32_t size = 0)
|
/// c'tor taking the @p codec_name and @p site of the payload
|
||||||
: BaseMessage(message_type::kCodecHeader), payloadSize(size), payload(nullptr), codec(codecName)
|
explicit CodecHeader(const std::string& codec_name = "", uint32_t size = 0)
|
||||||
|
: BaseMessage(message_type::kCodecHeader), payloadSize(size), payload(nullptr), codec(codec_name)
|
||||||
{
|
{
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
payload = static_cast<char*>(malloc(size * sizeof(char)));
|
payload = static_cast<char*>(malloc(size * sizeof(char)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~CodecHeader() override
|
~CodecHeader() override
|
||||||
{
|
{
|
||||||
free(payload);
|
free(payload);
|
||||||
|
@ -54,8 +56,11 @@ public:
|
||||||
return static_cast<uint32_t>(sizeof(uint32_t) + codec.size() + sizeof(uint32_t) + payloadSize);
|
return static_cast<uint32_t>(sizeof(uint32_t) + codec.size() + sizeof(uint32_t) + payloadSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// payload size
|
||||||
uint32_t payloadSize;
|
uint32_t payloadSize;
|
||||||
|
/// the payload
|
||||||
char* payload;
|
char* payload;
|
||||||
|
/// name of the codec
|
||||||
std::string codec;
|
std::string codec;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -65,7 +70,5 @@ protected:
|
||||||
writeVal(stream, payload, payloadSize);
|
writeVal(stream, payload, payloadSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2024 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -30,15 +30,16 @@
|
||||||
namespace msg
|
namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Cast a BaseMessage @message to type "ToType"
|
||||||
|
/// @return castest message or nullptr, if the cast failed
|
||||||
template <typename ToType>
|
template <typename ToType>
|
||||||
static std::unique_ptr<ToType> message_cast(std::unique_ptr<msg::BaseMessage> message)
|
static std::unique_ptr<ToType> message_cast(std::unique_ptr<msg::BaseMessage> message)
|
||||||
{
|
{
|
||||||
ToType* tmp = dynamic_cast<ToType*>(message.get());
|
auto* tmp = dynamic_cast<ToType*>(message.get());
|
||||||
std::unique_ptr<ToType> result;
|
|
||||||
if (tmp != nullptr)
|
if (tmp != nullptr)
|
||||||
{
|
{
|
||||||
message.release();
|
message.release();
|
||||||
result.reset(tmp);
|
std::unique_ptr<ToType> result(tmp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -47,6 +48,7 @@ static std::unique_ptr<ToType> message_cast(std::unique_ptr<msg::BaseMessage> me
|
||||||
namespace factory
|
namespace factory
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Create a message of type T from @p base_message beaser and payload @p buffer
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::unique_ptr<T> createMessage(const BaseMessage& base_message, char* buffer)
|
static std::unique_ptr<T> createMessage(const BaseMessage& base_message, char* buffer)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +59,7 @@ static std::unique_ptr<T> createMessage(const BaseMessage& base_message, char* b
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a BaseMessage from @p base_message header and payload @p buffer
|
||||||
static std::unique_ptr<BaseMessage> createMessage(const BaseMessage& base_message, char* buffer)
|
static std::unique_ptr<BaseMessage> createMessage(const BaseMessage& base_message, char* buffer)
|
||||||
{
|
{
|
||||||
std::unique_ptr<BaseMessage> result;
|
std::unique_ptr<BaseMessage> result;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,7 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_HELLO_HPP
|
#pragma once
|
||||||
#define MESSAGE_HELLO_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "common/str_compat.hpp"
|
#include "common/str_compat.hpp"
|
||||||
|
@ -31,16 +30,20 @@
|
||||||
namespace msg
|
namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Hello message
|
||||||
|
/// Initial message, sent from client to server
|
||||||
class Hello : public JsonMessage
|
class Hello : public JsonMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// c'tor
|
||||||
Hello() : JsonMessage(message_type::kHello)
|
Hello() : JsonMessage(message_type::kHello)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Hello(const std::string& macAddress, const std::string& id, size_t instance) : JsonMessage(message_type::kHello)
|
/// c'tor taking @p macAddress, @p id and @p instance
|
||||||
|
Hello(const std::string& mac_address, const std::string& id, size_t instance) : JsonMessage(message_type::kHello)
|
||||||
{
|
{
|
||||||
msg["MAC"] = macAddress;
|
msg["MAC"] = mac_address;
|
||||||
msg["HostName"] = ::getHostName();
|
msg["HostName"] = ::getHostName();
|
||||||
msg["Version"] = VERSION;
|
msg["Version"] = VERSION;
|
||||||
msg["ClientName"] = "Snapclient";
|
msg["ClientName"] = "Snapclient";
|
||||||
|
@ -51,53 +54,64 @@ public:
|
||||||
msg["SnapStreamProtocolVersion"] = 2;
|
msg["SnapStreamProtocolVersion"] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~Hello() override = default;
|
~Hello() override = default;
|
||||||
|
|
||||||
|
/// @return the MAC address
|
||||||
std::string getMacAddress() const
|
std::string getMacAddress() const
|
||||||
{
|
{
|
||||||
return msg["MAC"];
|
return msg["MAC"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the host name
|
||||||
std::string getHostName() const
|
std::string getHostName() const
|
||||||
{
|
{
|
||||||
return msg["HostName"];
|
return msg["HostName"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the client version
|
||||||
std::string getVersion() const
|
std::string getVersion() const
|
||||||
{
|
{
|
||||||
return msg["Version"];
|
return msg["Version"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the client name (e.g. "Snapclient")
|
||||||
std::string getClientName() const
|
std::string getClientName() const
|
||||||
{
|
{
|
||||||
return msg["ClientName"];
|
return msg["ClientName"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the OS name
|
||||||
std::string getOS() const
|
std::string getOS() const
|
||||||
{
|
{
|
||||||
return msg["OS"];
|
return msg["OS"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the CPU architecture
|
||||||
std::string getArch() const
|
std::string getArch() const
|
||||||
{
|
{
|
||||||
return msg["Arch"];
|
return msg["Arch"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the instance id
|
||||||
int getInstance() const
|
int getInstance() const
|
||||||
{
|
{
|
||||||
return get("Instance", 1);
|
return get("Instance", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the protocol version
|
||||||
int getProtocolVersion() const
|
int getProtocolVersion() const
|
||||||
{
|
{
|
||||||
return get("SnapStreamProtocolVersion", 1);
|
return get("SnapStreamProtocolVersion", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return a unqiue machine ID
|
||||||
std::string getId() const
|
std::string getId() const
|
||||||
{
|
{
|
||||||
return get("ID", getMacAddress());
|
return get("ID", getMacAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return a unqiue client ID
|
||||||
std::string getUniqueId() const
|
std::string getUniqueId() const
|
||||||
{
|
{
|
||||||
std::string id = getId();
|
std::string id = getId();
|
||||||
|
@ -109,7 +123,5 @@ public:
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_JSON_HPP
|
#pragma once
|
||||||
#define MESSAGE_JSON_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "common/json.hpp"
|
#include "common/json.hpp"
|
||||||
|
@ -30,13 +30,16 @@ using json = nlohmann::json;
|
||||||
namespace msg
|
namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Base class of a message with json payload
|
||||||
class JsonMessage : public BaseMessage
|
class JsonMessage : public BaseMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JsonMessage(message_type msgType) : BaseMessage(msgType)
|
/// c'tor taking the @p msg_type
|
||||||
|
explicit JsonMessage(message_type msg_type) : BaseMessage(msg_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~JsonMessage() override = default;
|
~JsonMessage() override = default;
|
||||||
|
|
||||||
void read(std::istream& stream) override
|
void read(std::istream& stream) override
|
||||||
|
@ -60,6 +63,7 @@ protected:
|
||||||
writeVal(stream, msg.dump());
|
writeVal(stream, msg.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return value for key @p what or @p def, if not found
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T get(const std::string& what, const T& def) const
|
T get(const std::string& what, const T& def) const
|
||||||
{
|
{
|
||||||
|
@ -75,7 +79,5 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -38,15 +38,17 @@ namespace msg
|
||||||
class PcmChunk : public WireChunk
|
class PcmChunk : public WireChunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PcmChunk(const SampleFormat& sampleFormat, uint32_t ms)
|
/// c'tor, construct from @p sample_format with duration @p ms
|
||||||
: WireChunk((sampleFormat.rate() * ms / 1000) * sampleFormat.frameSize()), format(sampleFormat), idx_(0)
|
PcmChunk(const SampleFormat& sample_format, uint32_t ms) : WireChunk((sample_format.rate() * ms / 1000) * sample_format.frameSize()), format(sample_format)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PcmChunk() : WireChunk(), idx_(0)
|
/// c'tor
|
||||||
|
PcmChunk() : WireChunk()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~PcmChunk() override = default;
|
~PcmChunk() override = default;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -73,16 +75,18 @@ public:
|
||||||
// return result;
|
// return result;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
int readFrames(void* outputBuffer, uint32_t frameCount)
|
/// Read the next @p frame_count frames into @p output_buffer, update the internal read position
|
||||||
|
/// @return number of frames copied to @p output_buffer
|
||||||
|
int readFrames(void* output_buffer, uint32_t frame_count)
|
||||||
{
|
{
|
||||||
// logd << "read: " << frameCount << ", total: " << (wireChunk->length / format.frameSize()) << ", idx: " << idx;// << "\n";
|
// logd << "read: " << frameCount << ", total: " << (wireChunk->length / format.frameSize()) << ", idx: " << idx;// << "\n";
|
||||||
int result = frameCount;
|
int result = frame_count;
|
||||||
if (idx_ + frameCount > (payloadSize / format.frameSize()))
|
if (idx_ + frame_count > (payloadSize / format.frameSize()))
|
||||||
result = (payloadSize / format.frameSize()) - idx_;
|
result = (payloadSize / format.frameSize()) - idx_;
|
||||||
|
|
||||||
// logd << ", from: " << format.frameSize()*idx << ", to: " << format.frameSize()*idx + format.frameSize()*result;
|
// logd << ", from: " << format.frameSize()*idx << ", to: " << format.frameSize()*idx + format.frameSize()*result;
|
||||||
if (outputBuffer != nullptr)
|
if (output_buffer != nullptr)
|
||||||
memcpy(static_cast<char*>(outputBuffer), static_cast<char*>(payload) + format.frameSize() * idx_, format.frameSize() * result);
|
memcpy(static_cast<char*>(output_buffer), static_cast<char*>(payload) + format.frameSize() * idx_, format.frameSize() * result);
|
||||||
|
|
||||||
idx_ += result;
|
idx_ += result;
|
||||||
// logd << ", new idx: " << idx << ", result: " << result << ", wireChunk->length: " << wireChunk->length << ", format.frameSize(): " <<
|
// logd << ", new idx: " << idx << ", result: " << result << ", wireChunk->length: " << wireChunk->length << ", format.frameSize(): " <<
|
||||||
|
@ -90,6 +94,8 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// seek @p frames forward or backward
|
||||||
|
/// @return the new read position
|
||||||
int seek(int frames)
|
int seek(int frames)
|
||||||
{
|
{
|
||||||
if ((frames < 0) && (-frames > static_cast<int>(idx_)))
|
if ((frames < 0) && (-frames > static_cast<int>(idx_)))
|
||||||
|
@ -102,17 +108,20 @@ public:
|
||||||
return idx_;
|
return idx_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return start time of the current frame
|
||||||
chronos::time_point_clk start() const override
|
chronos::time_point_clk start() const override
|
||||||
{
|
{
|
||||||
return chronos::time_point_clk(chronos::sec(timestamp.sec) + chronos::usec(timestamp.usec) +
|
return chronos::time_point_clk(chronos::sec(timestamp.sec) + chronos::usec(timestamp.usec) +
|
||||||
chronos::usec(static_cast<chronos::usec::rep>(1000000. * ((double)idx_ / (double)format.rate()))));
|
chronos::usec(static_cast<chronos::usec::rep>(1000000. * ((double)idx_ / (double)format.rate()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return time of the last frame
|
||||||
inline chronos::time_point_clk end() const
|
inline chronos::time_point_clk end() const
|
||||||
{
|
{
|
||||||
return start() + durationLeft<chronos::usec>();
|
return start() + durationLeft<chronos::usec>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return duration of this chunk
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T duration() const
|
inline T duration() const
|
||||||
{
|
{
|
||||||
|
@ -127,42 +136,51 @@ public:
|
||||||
// payloadSize = newSize;
|
// payloadSize = newSize;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void setFrameCount(int frameCount)
|
/// Set the @p frame_count, reserve memory
|
||||||
|
void setFrameCount(int frame_count)
|
||||||
{
|
{
|
||||||
auto newSize = format.frameSize() * frameCount;
|
auto new_size = format.frameSize() * frame_count;
|
||||||
payload = static_cast<char*>(realloc(payload, newSize));
|
payload = static_cast<char*>(realloc(payload, new_size));
|
||||||
payloadSize = newSize;
|
payloadSize = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return duration of this chunk in [ms]
|
||||||
double durationMs() const
|
double durationMs() const
|
||||||
{
|
{
|
||||||
return static_cast<double>(getFrameCount()) / format.msRate();
|
return static_cast<double>(getFrameCount()) / format.msRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return time left, starting from the read pointer
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T durationLeft() const
|
inline T durationLeft() const
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<T>(chronos::nsec(static_cast<chronos::nsec::rep>(1000000 * (getFrameCount() - idx_) / format.msRate())));
|
return std::chrono::duration_cast<T>(chronos::nsec(static_cast<chronos::nsec::rep>(1000000 * (getFrameCount() - idx_) / format.msRate())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return true if the read pointer is at the end
|
||||||
inline bool isEndOfChunk() const
|
inline bool isEndOfChunk() const
|
||||||
{
|
{
|
||||||
return idx_ >= getFrameCount();
|
return idx_ >= getFrameCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return number of frames
|
||||||
inline uint32_t getFrameCount() const
|
inline uint32_t getFrameCount() const
|
||||||
{
|
{
|
||||||
return (payloadSize / format.frameSize());
|
return (payloadSize / format.frameSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return number of samples
|
||||||
inline uint32_t getSampleCount() const
|
inline uint32_t getSampleCount() const
|
||||||
{
|
{
|
||||||
return (payloadSize / format.sampleSize());
|
return (payloadSize / format.sampleSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sample format of this chunk
|
||||||
SampleFormat format;
|
SampleFormat format;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// current read position (frame idx)
|
||||||
uint32_t idx_ = 0;
|
uint32_t idx_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,7 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_SERVER_SETTINGS_HPP
|
#pragma once
|
||||||
#define MESSAGE_SERVER_SETTINGS_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "json_message.hpp"
|
#include "json_message.hpp"
|
||||||
|
@ -26,9 +25,11 @@
|
||||||
namespace msg
|
namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Dynamic settings that affect the client
|
||||||
class ServerSettings : public JsonMessage
|
class ServerSettings : public JsonMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// c'tor
|
||||||
ServerSettings() : JsonMessage(message_type::kServerSettings)
|
ServerSettings() : JsonMessage(message_type::kServerSettings)
|
||||||
{
|
{
|
||||||
setBufferMs(0);
|
setBufferMs(0);
|
||||||
|
@ -37,51 +38,57 @@ public:
|
||||||
setMuted(false);
|
setMuted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~ServerSettings() override = default;
|
~ServerSettings() override = default;
|
||||||
|
|
||||||
|
/// @return the end to end delay in [ms]
|
||||||
int32_t getBufferMs()
|
int32_t getBufferMs()
|
||||||
{
|
{
|
||||||
return get("bufferMs", 0);
|
return get("bufferMs", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return client specific additional latency in [ms]
|
||||||
int32_t getLatency()
|
int32_t getLatency()
|
||||||
{
|
{
|
||||||
return get("latency", 0);
|
return get("latency", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return the volume in [%]
|
||||||
uint16_t getVolume()
|
uint16_t getVolume()
|
||||||
{
|
{
|
||||||
return get("volume", static_cast<uint16_t>(100));
|
return get("volume", static_cast<uint16_t>(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return if muted
|
||||||
bool isMuted()
|
bool isMuted()
|
||||||
{
|
{
|
||||||
return get("muted", false);
|
return get("muted", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Set the end to end delay to @p buffer_ms [ms]
|
||||||
void setBufferMs(int32_t bufferMs)
|
void setBufferMs(int32_t buffer_ms)
|
||||||
{
|
{
|
||||||
msg["bufferMs"] = bufferMs;
|
msg["bufferMs"] = buffer_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the additional client specific @p latency [ms]
|
||||||
void setLatency(int32_t latency)
|
void setLatency(int32_t latency)
|
||||||
{
|
{
|
||||||
msg["latency"] = latency;
|
msg["latency"] = latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the @p volume [%]
|
||||||
void setVolume(uint16_t volume)
|
void setVolume(uint16_t volume)
|
||||||
{
|
{
|
||||||
msg["volume"] = volume;
|
msg["volume"] = volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set client to @p muted
|
||||||
void setMuted(bool muted)
|
void setMuted(bool muted)
|
||||||
{
|
{
|
||||||
msg["muted"] = muted;
|
msg["muted"] = muted;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2022 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,8 +16,7 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef MESSAGE_TIME_HPP
|
#pragma once
|
||||||
#define MESSAGE_TIME_HPP
|
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
@ -25,13 +24,16 @@
|
||||||
namespace msg
|
namespace msg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Time sync message, send from client to server and back
|
||||||
class Time : public BaseMessage
|
class Time : public BaseMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// c'tor
|
||||||
Time() : BaseMessage(message_type::kTime)
|
Time() : BaseMessage(message_type::kTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// d'tor
|
||||||
~Time() override = default;
|
~Time() override = default;
|
||||||
|
|
||||||
void read(std::istream& stream) override
|
void read(std::istream& stream) override
|
||||||
|
@ -45,6 +47,7 @@ public:
|
||||||
return sizeof(tv);
|
return sizeof(tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The latency after round trip "client => server => client"
|
||||||
tv latency;
|
tv latency;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -54,7 +57,5 @@ protected:
|
||||||
writeVal(stream, latency.usec);
|
writeVal(stream, latency.usec);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msg
|
} // namespace msg
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue