mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-26 20:56:42 +01:00
107 lines
5.4 KiB
C++
107 lines
5.4 KiB
C++
#include "Extension/Music/local_music_playback_policy.h"
|
|
#include <cstdio>
|
|
|
|
namespace policy = dingosdk::profile_runtime::music_playback;
|
|
|
|
int main() {
|
|
int failures = 0;
|
|
const auto check = [&](bool ok, const char* message) {
|
|
if (!ok) { std::printf("FAIL: %s\n", message); ++failures; }
|
|
};
|
|
|
|
check(policy::cursor_sync_sentinel == 0x7fffffffu,
|
|
"native cursor synchronization sentinel is INT_MAX, distinct from queue -1");
|
|
|
|
check(policy::resolve_playlist_binding_id(0, 1, true) == 1,
|
|
"a zero-ID dynamic Favorites binding resolves to its live native node");
|
|
check(policy::resolve_playlist_binding_id(0, 1, false) == 0,
|
|
"a zero-ID binding stays untouched when the Favorites node is unavailable");
|
|
check(policy::resolve_playlist_binding_id(18, 1, true) == 18,
|
|
"ordinary playlist bindings are not redirected to Favorites");
|
|
|
|
check(policy::ordered_member_index(0, 4, true) == 3 &&
|
|
policy::ordered_member_index(3, 4, true) == 0,
|
|
"Favorites sequential order follows the visible top-to-bottom rows");
|
|
check(policy::ordered_member_index(0, 4, false) == 0 &&
|
|
policy::ordered_member_index(4, 4, true) == 4,
|
|
"native static order stays forward and invalid positions are rejected");
|
|
|
|
// The queue's global candidate asset pool can contain hundreds of songs while
|
|
// the selected native playlist contains only its authored subset.
|
|
std::array<std::uint8_t, 32> two_track_members{};
|
|
two_track_members[0] = 0x12;
|
|
two_track_members[16] = 0x34;
|
|
const std::array<std::uint8_t, 16> second_track{0x34};
|
|
std::uint32_t member_position{};
|
|
check(policy::find_member_position(two_track_members.data(), 2, second_track, member_position) &&
|
|
member_position == 1,
|
|
"active current-song GUID is resolved against a playlist subset, independent of candidate-pool size");
|
|
|
|
auto plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, true, false, false, 0, 0);
|
|
check(plan.mode == policy::native_sequential_mode && plan.set_mode,
|
|
"sequential is selected when shuffle is off");
|
|
check(plan.set_cursor && plan.cursor == 0, "a new sequential playlist starts at authored entry zero");
|
|
|
|
plan = policy::plan_cursor(true, policy::native_sequential_mode, 4,
|
|
false, false, true, 3, 6);
|
|
check(plan.mode == policy::native_default_mode && plan.set_mode && !plan.set_cursor,
|
|
"shuffle restores native default selection without moving its cursor");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, false, true, true, 2, 6);
|
|
check(plan.set_mode && plan.set_cursor && plan.cursor == policy::cursor_sync_sentinel,
|
|
"a pending explicit song request keeps native GUID synchronization");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, false, false, true, 0, 6);
|
|
check(plan.set_mode && plan.cursor == 1,
|
|
"turning shuffle off mid-play continues after the current first track");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, false, false, true, 5, 6);
|
|
check(plan.cursor == 0, "sequential playback wraps after the final playlist entry");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode, 3,
|
|
false, false, true, 2, 6);
|
|
check(!plan.set_mode && !plan.set_cursor && plan.cursor == 3,
|
|
"an active sequential cursor keeps progressing without being reseeded");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode, 3,
|
|
true, false, true, 2, 6);
|
|
check(plan.set_cursor && plan.cursor == 0,
|
|
"a newly selected playlist starts at its first entry even if its current GUID matches");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode, 0,
|
|
true, false, false, 0, 2);
|
|
check(plan.set_cursor && plan.cursor == 0,
|
|
"new playlist identity explicitly seeds entry zero even when the prior cursor was also zero");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, false, false, false, 0, 6);
|
|
check(plan.cursor == 0, "an unresolvable current track safely restarts at the first entry");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_default_mode,
|
|
policy::cursor_sync_sentinel, true, false, false, 0, 3);
|
|
check(plan.set_mode && plan.set_cursor && plan.cursor == 0,
|
|
"a dynamic Favorites playlist can start sequentially without a static asset GUID");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode, 3,
|
|
false, false, false, 0, 3);
|
|
check(plan.set_cursor && plan.cursor == 0,
|
|
"a favorite removal that leaves the cursor at member count restarts on a valid member");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode, 3,
|
|
false, false, true, 1, 3);
|
|
check(plan.set_cursor && plan.cursor == 2,
|
|
"a stale dynamic cursor resumes after the active member when its GUID is available");
|
|
|
|
plan = policy::plan_cursor(false, policy::native_sequential_mode,
|
|
policy::cursor_sync_sentinel, false, false, false, 0, 6);
|
|
check(!plan.set_mode && plan.set_cursor && plan.cursor == 0,
|
|
"a stale sync sentinel without a pending click cannot strand sequential selection");
|
|
|
|
std::printf(failures ? "%d failure(s)\n" : "all passed\n", failures);
|
|
return failures ? 1 : 0;
|
|
}
|