Skip to content

Commit 1764cbb

Browse files
committed
split into headers, use actual queue
1 parent 648e906 commit 1764cbb

File tree

8 files changed

+281
-181
lines changed

8 files changed

+281
-181
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ project(discord-rpc)
55
set(CMAKE_CXX_STANDARD 23)
66
include(cmake/CPM.cmake)
77

8-
add_library(${PROJECT_NAME} STATIC src/discord-rpc.cpp src/serialization.cpp)
8+
add_library(${PROJECT_NAME} STATIC src/discord-rpc.cpp src/serialization.cpp src/command-queue.cpp)
99
target_include_directories(${PROJECT_NAME} PUBLIC include)
1010

1111
# Windows has some extra code

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ A simple Discord Rich Presence library for C++ made from scratch.
66
**Checklist**:
77
- [x] Handshake
88
- [x] Update presence with custom data
9-
- [x] Buttons support
9+
- [x] More features (buttons, activity type, etc.)
1010
- [x] Linux support
1111
- [x] MacOS support
1212
- [x] Windows support
1313
- [x] Out-of-the-box Wine support *(Only supports Wine Staging 10.2+ because of AF_UNIX socket support)*
1414
- [ ] Events (join, spectate, etc.)
1515
- [ ] Auto register (for steam games)
16+
- [ ] Social SDK features
1617
- [ ] Documentation
1718
- [ ] Examples
1819

@@ -26,7 +27,7 @@ that uses a modern C++ style and has more features.
2627

2728
### Features
2829
- **Modern C++**: This library is written in C++23 and follows builder patterns as much as possible.
29-
- **Buttons**: Undocumented/unimplemented feature in discord, that allows you to add custom links to your presence.
30+
- **More features**: Implements new features from Discord RPC documentation that is not present in the original library, such as buttons, activity type, and more.
3031
- **Project integration**: Say goodbye to copying library files or dealing with RapidJSON errors. This library can be easily integrated into your project without any hassle.
3132
- **Cross-platform**: This library is designed to work on all supported platforms, including Linux, macOS, and Windows.
3233
- **Wine support**: Library provides internal layer to support Wine, no extra configuration needed.

include/discord-rpc.hpp

Lines changed: 4 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <mutex>
1111
#include <string>
1212

13+
#include "discord-rpc/commands.hpp"
14+
#include "discord-rpc/presence.hpp"
15+
1316
namespace discord {
1417
class Connection;
1518
struct IOWorker;
@@ -25,155 +28,6 @@ namespace discord {
2528
int premium_type = 0;
2629
};
2730

28-
enum class PartyPrivacy : int32_t {
29-
Private = 0,
30-
Public = 1,
31-
};
32-
33-
enum class ActivityType : int32_t {
34-
Game = 0,
35-
Streaming = 1,
36-
Listening = 2,
37-
Watching = 3,
38-
Custom = 4, // Note: only works for bot accounts
39-
Competing = 5,
40-
};
41-
42-
enum class StatusDisplayType {
43-
Name = 0,
44-
State = 1,
45-
Details = 2,
46-
};
47-
48-
class Presence {
49-
public:
50-
#define GENERATE_GETSET_LRVALUE(type, name, member) \
51-
Presence& set##name(type const& member) noexcept { m_##member = member; return *this; } \
52-
Presence& set##name(type&& member) noexcept { m_##member = std::move(member); return *this; }\
53-
type const& get##name() const noexcept { return m_##member; }
54-
55-
#define GENERATE_GETSET_VALUE(type, name, member) \
56-
Presence& set##name(type member) noexcept { m_##member = member; return *this; } \
57-
type get##name() const noexcept { return m_##member; }
58-
59-
#define GENERATE_GETSET_BUTTON(index) \
60-
Button& getButton##index() noexcept { return m_buttons[index - 1]; } \
61-
Button const& getButton##index() const noexcept { return m_buttons[index - 1]; } \
62-
Presence& setButton##index(Button const& button) noexcept { m_buttons[index - 1] = button; return *this; } \
63-
Presence& setButton##index(Button&& button) noexcept { m_buttons[index - 1] = std::move(button); return *this; } \
64-
Presence& setButton##index(std::string const& label, std::string const& url, bool enabled = true) noexcept { \
65-
m_buttons[index - 1].set(label, url, enabled); \
66-
return *this; \
67-
} \
68-
Presence& setButton##index(std::string&& label, std::string&& url, bool enabled = true) noexcept { \
69-
m_buttons[index - 1].set(std::move(label), std::move(url), enabled); \
70-
return *this; \
71-
}
72-
73-
class Button {
74-
public:
75-
[[nodiscard]] bool isEnabled() const noexcept { return enabled; }
76-
[[nodiscard]] std::string const& getLabel() const noexcept { return label; }
77-
[[nodiscard]] std::string const& getURL() const noexcept { return url; }
78-
79-
Button& setEnabled(bool enabled) noexcept {
80-
this->enabled = enabled;
81-
return *this;
82-
}
83-
84-
Button& setLabel(std::string const& label) noexcept {
85-
this->label = label;
86-
return *this;
87-
}
88-
89-
Button& setLabel(std::string&& label) noexcept {
90-
this->label = std::move(label);
91-
return *this;
92-
}
93-
94-
Button& setURL(std::string const& url) noexcept {
95-
this->url = url;
96-
return *this;
97-
}
98-
99-
Button& setURL(std::string&& url) noexcept {
100-
this->url = std::move(url);
101-
return *this;
102-
}
103-
104-
Button& set(std::string const& label, std::string const& url, bool enabled = true) noexcept {
105-
this->label = label;
106-
this->url = url;
107-
this->enabled = enabled;
108-
return *this;
109-
}
110-
111-
Button& set(std::string&& label, std::string&& url, bool enabled = true) noexcept {
112-
this->label = std::move(label);
113-
this->url = std::move(url);
114-
this->enabled = enabled;
115-
return *this;
116-
}
117-
118-
private:
119-
bool enabled = false;
120-
std::string label;
121-
std::string url;
122-
};
123-
124-
GENERATE_GETSET_LRVALUE(std::string, State, state)
125-
GENERATE_GETSET_LRVALUE(std::string, Details, details)
126-
GENERATE_GETSET_VALUE(int64_t, StartTimestamp, startTimestamp)
127-
GENERATE_GETSET_VALUE(int64_t, EndTimestamp, endTimestamp)
128-
GENERATE_GETSET_LRVALUE(std::string, LargeImageKey, largeImageKey)
129-
GENERATE_GETSET_LRVALUE(std::string, LargeImageText, largeImageText)
130-
GENERATE_GETSET_LRVALUE(std::string, SmallImageKey, smallImageKey)
131-
GENERATE_GETSET_LRVALUE(std::string, SmallImageText, smallImageText)
132-
GENERATE_GETSET_LRVALUE(std::string, PartyID, partyID)
133-
GENERATE_GETSET_VALUE(int32_t, PartySize, partySize)
134-
GENERATE_GETSET_VALUE(int32_t, PartyMax, partyMax)
135-
GENERATE_GETSET_VALUE(PartyPrivacy, PartyPrivacy, partyPrivacy)
136-
GENERATE_GETSET_VALUE(ActivityType, ActivityType, activityType)
137-
GENERATE_GETSET_VALUE(StatusDisplayType, StatusDisplayType, statusDisplayType)
138-
GENERATE_GETSET_LRVALUE(std::string, MatchSecret, matchSecret)
139-
GENERATE_GETSET_LRVALUE(std::string, JoinSecret, joinSecret)
140-
GENERATE_GETSET_LRVALUE(std::string, SpectateSecret, spectateSecret)
141-
GENERATE_GETSET_VALUE(bool, Instance, instance)
142-
143-
GENERATE_GETSET_BUTTON(1)
144-
GENERATE_GETSET_BUTTON(2)
145-
146-
#undef GENERATE_GETSET_BUTTON
147-
#undef GENERATE_GETSET_LRVALUE
148-
#undef GENERATE_GETSET_VALUE
149-
150-
Presence& clear() noexcept;
151-
152-
/// Calls the RPCManager::refresh() function to update the presence
153-
void refresh() const noexcept;
154-
155-
private:
156-
std::string m_state;
157-
std::string m_details;
158-
int64_t m_startTimestamp = 0;
159-
int64_t m_endTimestamp = 0;
160-
std::string m_largeImageKey;
161-
std::string m_largeImageText;
162-
std::string m_smallImageKey;
163-
std::string m_smallImageText;
164-
std::string m_partyID;
165-
int32_t m_partySize = 0;
166-
int32_t m_partyMax = 0;
167-
PartyPrivacy m_partyPrivacy = PartyPrivacy::Private;
168-
ActivityType m_activityType = ActivityType::Game;
169-
StatusDisplayType m_statusDisplayType = StatusDisplayType::Name;
170-
std::string m_matchSecret;
171-
std::string m_joinSecret;
172-
std::string m_spectateSecret;
173-
std::array<Button, 2> m_buttons;
174-
bool m_instance = false;
175-
};
176-
17731
class RPCManager {
17832
private:
17933
// prevent construction from outside
@@ -274,9 +128,7 @@ namespace discord {
274128
std::chrono::time_point<std::chrono::system_clock> m_nextConnect = std::chrono::system_clock::now();
275129
size_t m_processID = 0;
276130
int m_nonce = 1;
277-
std::string m_queuedPresence{};
278-
std::mutex m_queuePresenceMutex{};
279-
std::atomic_bool m_updatePresence = false;
131+
CommandQueue m_commandQueue{};
280132
};
281133
}
282134

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
#ifndef DISCORD_RPC_COMMAND_QUEUE_HPP
3+
#define DISCORD_RPC_COMMAND_QUEUE_HPP
4+
5+
#include <queue>
6+
#include <mutex>
7+
#include <string>
8+
#include <optional>
9+
10+
namespace discord {
11+
/// @brief A simple command queue for Discord RPC commands
12+
class CommandQueue {
13+
public:
14+
CommandQueue() noexcept = default;
15+
~CommandQueue() noexcept = default;
16+
17+
/// @brief Adds a command to the queue
18+
void push(std::string const& command) noexcept;
19+
void push(std::string&& command) noexcept;
20+
21+
/// @brief Pushes a new command to the queue and returns a reference to the prepared command.
22+
/// Mutex remains locked after this call, so make sure to call `finish()` after filling the command.
23+
std::string& prepare() noexcept;
24+
25+
/// @brief Unlocks the mutex after a `prepare()` call.
26+
void finish() noexcept;
27+
28+
/// @brief Pops a command from the queue
29+
std::optional<std::string> pop() noexcept;
30+
31+
/// @brief Checks if the queue is empty
32+
bool empty() const noexcept;
33+
34+
/// @brief Returns the size of the queue
35+
size_t size() const noexcept;
36+
37+
private:
38+
std::queue<std::string> m_queue; ///< The internal command queue
39+
mutable std::mutex m_mutex; ///< Mutex for thread safety
40+
};
41+
}
42+
43+
#endif // DISCORD_RPC_COMMAND_QUEUE_HPP

0 commit comments

Comments
 (0)