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