Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6f0dea8
Added macro atlas screen for OpenShock
stevenjwheeler Apr 8, 2026
a9a7570
Regenerated macro atlas
stevenjwheeler Apr 8, 2026
bf46520
Add OpenShock API client and screen
stevenjwheeler Apr 8, 2026
1498166
Register OpenShock screen to yip-boi menu
stevenjwheeler Apr 8, 2026
5206aff
Register and initialize OpenShock client
stevenjwheeler Apr 8, 2026
873dbe1
Add SHOCK glyph
stevenjwheeler Apr 8, 2026
093148e
Add YipOS OpenShock settings tab
stevenjwheeler Apr 8, 2026
e5a364c
Register new OpenShock tab to UI
stevenjwheeler Apr 8, 2026
ecd72a9
Add OpenShock files to build
stevenjwheeler Apr 8, 2026
4726b10
Update filename
stevenjwheeler Apr 8, 2026
2eada90
Added OpenShock enable toggle and warning message
stevenjwheeler Apr 8, 2026
633d591
Show intensity and duration as zeroed out when unavailable
stevenjwheeler Apr 8, 2026
59e2939
Replace OpenShock tab with new general Shock tab in UI
stevenjwheeler Apr 9, 2026
60718c0
Add new ShockManager and client interface for multiple backends (open…
stevenjwheeler Apr 9, 2026
4800d95
Update atlas frame name from OpenShock to Shock
stevenjwheeler Apr 9, 2026
960ce7d
Generalize shock screen
stevenjwheeler Apr 9, 2026
92c7454
Modify OpenShockClient to use new ShockManager interface
stevenjwheeler Apr 9, 2026
de4a680
Update Screens to point to new unified shock screen
stevenjwheeler Apr 9, 2026
d879d5a
Add new PiShockClient
stevenjwheeler Apr 9, 2026
3bb2aed
Initialize new ShockManager
stevenjwheeler Apr 9, 2026
66fd2d4
Change UIManager entries to hold Shock tab states
stevenjwheeler Apr 9, 2026
8154884
Add new Shock files and PiShockClient to build
stevenjwheeler Apr 9, 2026
bc2199b
Merge pull request #1 from stevenjwheeler/pishock
stevenjwheeler Apr 9, 2026
7d89243
Generalize Shock tab name function
stevenjwheeler Apr 9, 2026
52cb111
Rename variables to match new name, update description of module and …
stevenjwheeler Apr 9, 2026
2758c5f
Tidy up variables and rename from openshock to shock
stevenjwheeler Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified WilliamsTube_MacroAtlas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 34 additions & 1 deletion generate_macro_atlas.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
]

TILE_LABELS_P2 = [
["DBG", "TWTCH", "INTRP", "-----", "DM"],
["DBG", "TWTCH", "INTRP", "SHOCK", "DM"],
["-----", "-----", "-----", "-----", "-----"],
["-----", "-----", "-----", "-----", "-----"],
]
Expand Down Expand Up @@ -806,6 +806,38 @@ def layout_dm_compose(buf):
buf.put_status_bar()


def layout_shock(buf):
"""Shock control screen: frame + labels + Execute button."""
buf.put_frame("SHOCK")

# Row 1 (ty=0): Shocker Selection
buf.put_text(3, 1, " < ", inverted=True) # tx=0
buf.put_text(34, 1, " > ", inverted=True) # tx=4

# Row 2: Separator
buf.put_hline(2)

# Row 3: Status
buf.put_text(4, 3, "ACTIVE MODE:")

# Row 4 (ty=1): Intensity & Duration on same line
# tx=0: Int -, tx=2: Int +, tx=3: Dur -, tx=4: Dur +
buf.put_text(2, 4, " - ", inverted=True) # tx=0
buf.put_text(16, 4, " + ", inverted=True) # tx=2
buf.put_text(24, 4, " - ", inverted=True) # tx=3
buf.put_text(34, 4, " + ", inverted=True) # tx=4

# Row 5 : Separator
buf.put_hline(5)

# Row 6 (ty=2): Mode & Execute
# tx=0-1: MODE button (11 chars), tx=3-4: EXECUTE button (11 chars)
buf.put_text(2, 6, " [ MODE ] ", inverted=True) # tx=0-1
buf.put_text(25, 6, " [ EXECUTE ] ", inverted=True) # tx=3-4

buf.put_status_bar()


def layout_dm_pair(buf):
"""DM Pair CHOOSE mode: frame + DIAL/SCAN buttons + hint text."""
buf.put_frame("DM PAIR")
Expand Down Expand Up @@ -909,6 +941,7 @@ def layout_dm_pair_joined(buf):
45: ("PAIR OK", layout_dm_pair_complete),
46: ("PAIR FAIL", layout_dm_pair_failed),
47: ("PAIR JOIN", layout_dm_pair_joined),
48: ("SHOCK", layout_shock),
}


Expand Down
5 changes: 5 additions & 0 deletions yip_os/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ set(YIPOS_SOURCES
src/screens/DMPairScreen.cpp
src/screens/DMComposeScreen.cpp
src/screens/DMMessageScreen.cpp
src/screens/ShockScreen.cpp
src/net/DMClient.cpp
src/net/OpenShockClient.cpp
src/net/PiShockClient.cpp
src/net/ShockManager.cpp
src/img/QRGen.cpp
src/translate/TranslationWorker.cpp
src/img/VQEncoder.cpp
Expand All @@ -164,6 +168,7 @@ set(YIPOS_SOURCES
src/ui/UIManager_Data.cpp
src/ui/UIManager_Config.cpp
src/ui/UIManager_DM.cpp
src/ui/UIManager_Shock.cpp
)

# Platform-specific sources
Expand Down
7 changes: 6 additions & 1 deletion yip_os/src/app/PDAController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "net/TwitchClient.hpp"
#include "media/MediaController.hpp"
#include "platform/SystemStats.hpp"
#include "net/ShockManager.hpp"
#include "core/Glyphs.hpp"
#include "core/Config.hpp"
#include "core/Logger.hpp"
Expand Down Expand Up @@ -97,6 +98,10 @@ PDAController::PDAController(PDADisplay& display, NetTracker& net_tracker, Confi
}
}

// Initialize shock manager
shock_manager_ = std::make_unique<ShockManager>();
shock_manager_->InitFromConfig(config_);

// Push home screen as root
auto home = std::make_unique<HomeScreen>(*this);
screen_stack_.push_back(std::move(home));
Expand Down Expand Up @@ -819,4 +824,4 @@ void PDAController::RefreshStockCache() {
stock_client_->FetchAll(window);
}

} // namespace YipOS
} // namespace YipOS
7 changes: 6 additions & 1 deletion yip_os/src/app/PDAController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class StockClient;
class TwitchClient;
struct TwitchMessage;
class TranslationWorker;
class ShockManager;

class PDAController {
public:
Expand Down Expand Up @@ -141,6 +142,9 @@ class PDAController {
void RefreshChatCache();
void MarkChatSeen();

// OpenShock & PiShock integration
ShockManager* GetShockManager() { return shock_manager_.get(); }

// Hard lock (full LOCK screen from home tile)
void SetLocked(bool locked);
bool IsLocked() const { return locked_; }
Expand Down Expand Up @@ -231,6 +235,7 @@ class PDAController {
std::unique_ptr<StockClient> stock_client_;
std::unique_ptr<TwitchClient> twitch_client_;
const TwitchMessage* selected_twitch_ = nullptr;
std::unique_ptr<ShockManager> shock_manager_;
std::string assets_path_;
std::unique_ptr<AudioPlayer> dm_notify_sound_;
bool prev_has_unseen_dm_ = false;
Expand Down Expand Up @@ -292,4 +297,4 @@ class PDAController {
std::array<std::atomic<int>, SPVR_DEVICE_COUNT> spvr_status_{};
};

} // namespace YipOS
} // namespace YipOS
2 changes: 1 addition & 1 deletion yip_os/src/core/Glyphs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ constexpr TileLabel TILE_LABELS[HOME_PAGES][TILE_ROWS][TILE_COLS] = {
{{"VRCX"}, {"HEART"}, {"BFI"}, {"STONK"}, {"CHAT"}},
{{"CC"}, {"AVTR"}, {"TEXT"}, {"MEDIA"}, {"LOCK"}}},
// Page 1
{{{"DBG"}, {"TWTCH"}, {"INTRP"}, {"-----"}, {"DM"}},
{{{"DBG"}, {"TWTCH"}, {"INTRP"}, {"SHOCK"}, {"DM"}},
{{"-----"}, {"-----"}, {"-----"}, {"-----"}, {"-----"}},
{{"-----"}, {"-----"}, {"-----"}, {"-----"}, {"-----"}}},
};
Expand Down
45 changes: 45 additions & 0 deletions yip_os/src/net/IShockClient.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* IShockClient.hpp
* V1.0.0
*
* Interface for Shock API integration to YipOS for remote control of
* OpenShock and PiShock devices.
*
* By otter_oasis
*/

#pragma once

#include <string>
#include <vector>

namespace YipOS {

struct Shocker {
std::string id;
std::string name;
bool is_owned = false;
std::string backend; // "openshock" or "pishock"
};

class IShockClient {
public:
virtual ~IShockClient() = default;

virtual void SetEnabled(bool enabled) = 0;
virtual bool HasConfig() const = 0;
virtual bool IsTokenValid() const = 0;
virtual bool IsEnabled() const = 0;

virtual bool FetchShockers() = 0;
virtual const std::vector<Shocker> &GetShockers() const = 0;

virtual bool SendControl(const std::string &shocker_id,
const std::string &type, float intensity,
int duration_ms) = 0;

virtual int GetMinDurationMs() const = 0;
virtual int GetMaxDurationMs() const = 0;
};

} // namespace YipOS
Loading