yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
music_playback_control_panel.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_MUSIC_PANELS_MUSIC_PLAYBACK_CONTROL_PANEL_H_
2#define YAZE_APP_EDITOR_MUSIC_PANELS_MUSIC_PLAYBACK_CONTROL_PANEL_H_
3
4#include <array>
5#include <chrono>
6#include <cmath>
7#include <cstdint>
8#include <cstdio>
9#include <functional>
10#include <string>
11
14#include "app/gui/core/icons.h"
15#include "app/gui/core/input.h"
19#include "imgui/imgui.h"
21
22namespace yaze {
23namespace editor {
24
30 public:
32 int* current_song_index,
33 music::MusicPlayer* music_player)
34 : music_bank_(music_bank),
35 current_song_index_(current_song_index),
36 music_player_(music_player) {}
37
38 // ==========================================================================
39 // WindowContent Identity
40 // ==========================================================================
41
42 std::string GetId() const override { return "music.tracker"; }
43 std::string GetDisplayName() const override { return "Playback Control"; }
44 std::string GetIcon() const override { return ICON_MD_PLAY_CIRCLE; }
45 std::string GetEditorCategory() const override { return "Music"; }
46 int GetPriority() const override { return 10; }
47
48 // ==========================================================================
49 // Callback Setters
50 // ==========================================================================
51
52 void SetOnOpenSong(std::function<void(int)> callback) {
53 on_open_song_ = callback;
54 }
55
56 void SetOnOpenPianoRoll(std::function<void(int)> callback) {
57 on_open_piano_roll_ = callback;
58 }
59
60 // ==========================================================================
61 // WindowContent Drawing
62 // ==========================================================================
63
64 void Draw(bool* p_open) override {
66 ImGui::TextDisabled("Music system not initialized");
67 return;
68 }
69
71 ImGui::Separator();
75
76 // Debug controls (collapsed by default)
78
79 // Help section (collapsed by default)
80 if (ImGui::CollapsingHeader(ICON_MD_KEYBOARD " Keyboard Shortcuts")) {
81 ImGui::BulletText("Space: Play/Pause toggle");
82 ImGui::BulletText("Escape: Stop playback");
83 ImGui::BulletText("+/-: Increase/decrease speed");
84 ImGui::BulletText("Arrow keys: Navigate in tracker/piano roll");
85 ImGui::BulletText("Z,S,X,D,C,V,G,B,H,N,J,M: Piano keyboard (C to B)");
86 ImGui::BulletText("Ctrl+Wheel: Zoom (Piano Roll)");
87 }
88 }
89
90 private:
91 void DrawToolset() {
92 auto state =
94 bool can_play = music_player_ && music_player_->IsAudioReady();
96
97 if (!can_play)
98 ImGui::BeginDisabled();
99
100 // Transport controls
101 if (state.is_playing && !state.is_paused) {
102 gui::StyleColorGuard pause_guard(ImGuiCol_Button,
104 if (ImGui::Button(ICON_MD_PAUSE "##Pause"))
106 if (ImGui::IsItemHovered())
107 ImGui::SetTooltip("Pause (Space)");
108 } else if (state.is_paused) {
109 gui::StyleColorGuard resume_guard(ImGuiCol_Button,
111 if (ImGui::Button(ICON_MD_PLAY_ARROW "##Resume"))
113 if (ImGui::IsItemHovered())
114 ImGui::SetTooltip("Resume (Space)");
115 } else {
116 if (ImGui::Button(ICON_MD_PLAY_ARROW "##Play"))
118 if (ImGui::IsItemHovered())
119 ImGui::SetTooltip("Play (Space)");
120 }
121
122 ImGui::SameLine();
123 if (ImGui::Button(ICON_MD_STOP "##Stop"))
125 if (ImGui::IsItemHovered())
126 ImGui::SetTooltip("Stop (Escape)");
127
128 if (!can_play)
129 ImGui::EndDisabled();
130
131 // Song label with playing indicator
132 ImGui::SameLine();
133 if (song) {
134 if (state.is_playing && !state.is_paused) {
135 float t = static_cast<float>(ImGui::GetTime() * 3.0);
136 float alpha = 0.5f + 0.5f * std::sin(t);
137 auto c = gui::GetSuccessColor();
138 ImGui::TextColored(ImVec4(c.x, c.y, c.z, alpha), ICON_MD_GRAPHIC_EQ);
139 ImGui::SameLine();
140 } else if (state.is_paused) {
141 ImGui::TextColored(gui::GetWarningColor(), ICON_MD_PAUSE_CIRCLE);
142 ImGui::SameLine();
143 }
144 ImGui::Text("%s", song->name.c_str());
145 if (song->modified) {
146 ImGui::SameLine();
147 ImGui::TextColored(gui::GetWarningColor(), ICON_MD_EDIT);
148 }
149 } else {
150 ImGui::TextDisabled("No song selected");
151 }
152
153 // Time display
154 if (state.is_playing || state.is_paused) {
155 ImGui::SameLine();
156 float seconds = state.ticks_per_second > 0
157 ? state.current_tick / state.ticks_per_second
158 : 0.0f;
159 int mins = static_cast<int>(seconds) / 60;
160 int secs = static_cast<int>(seconds) % 60;
161 ImGui::TextColored(gui::GetInfoColor(), " %d:%02d", mins, secs);
162 }
163
164 // Right-aligned controls
165 float right_offset = ImGui::GetWindowWidth() - 200;
166 if (right_offset > 200) {
167 ImGui::SameLine(right_offset);
168
169 ImGui::Text(ICON_MD_SPEED);
170 ImGui::SameLine();
171 ImGui::SetNextItemWidth(70);
172 float speed = state.playback_speed;
173 if (gui::SliderFloatWheel("##Speed", &speed, 0.25f, 2.0f, "%.2fx",
174 0.1f)) {
175 if (music_player_)
177 }
178 if (ImGui::IsItemHovered())
179 ImGui::SetTooltip("Playback speed (+/- keys)");
180
181 ImGui::SameLine();
182 ImGui::Text(ICON_MD_VOLUME_UP);
183 ImGui::SameLine();
184 ImGui::SetNextItemWidth(60);
185 if (gui::SliderIntWheel("##Vol", &current_volume_, 0, 100, "%d%%", 5)) {
186 if (music_player_)
188 }
189 if (ImGui::IsItemHovered())
190 ImGui::SetTooltip("Volume");
191 }
192 }
193
196
197 if (song) {
198 ImGui::Text("Selected Song:");
199 ImGui::SameLine();
200 ImGui::TextColored(gui::GetInfoColor(), "[%02X] %s",
201 *current_song_index_ + 1, song->name.c_str());
202
203 ImGui::SameLine();
204 ImGui::TextDisabled("| %zu segments", song->segments.size());
205 if (song->modified) {
206 ImGui::SameLine();
207 ImGui::TextColored(gui::GetWarningColor(), ICON_MD_EDIT " Modified");
208 }
209 }
210 }
211
213 auto state =
216
217 if (state.is_playing || state.is_paused) {
218 ImGui::Separator();
219
220 // Timeline progress
221 if (song && !song->segments.empty()) {
222 uint32_t total_duration = 0;
223 for (const auto& seg : song->segments) {
224 total_duration += seg.GetDuration();
225 }
226
227 float progress =
228 (total_duration > 0)
229 ? static_cast<float>(state.current_tick) / total_duration
230 : 0.0f;
231 progress = std::clamp(progress, 0.0f, 1.0f);
232
233 float current_seconds =
234 state.ticks_per_second > 0
235 ? state.current_tick / state.ticks_per_second
236 : 0.0f;
237 float total_seconds = state.ticks_per_second > 0
238 ? total_duration / state.ticks_per_second
239 : 0.0f;
240
241 int cur_min = static_cast<int>(current_seconds) / 60;
242 int cur_sec = static_cast<int>(current_seconds) % 60;
243 int tot_min = static_cast<int>(total_seconds) / 60;
244 int tot_sec = static_cast<int>(total_seconds) % 60;
245
246 ImGui::Text("%d:%02d / %d:%02d", cur_min, cur_sec, tot_min, tot_sec);
247 ImGui::SameLine();
248 ImGui::ProgressBar(progress, ImVec2(-1, 0), "");
249 }
250
251 ImGui::Text("Segment: %d | Tick: %u", state.current_segment_index + 1,
252 state.current_tick);
253 ImGui::SameLine();
254 ImGui::TextDisabled("| %.1f ticks/sec | %.2fx speed",
255 state.ticks_per_second, state.playback_speed);
256 }
257 }
258
260 ImGui::Separator();
261
262 if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Open Tracker")) {
263 if (on_open_song_)
265 }
266 if (ImGui::IsItemHovered())
267 ImGui::SetTooltip("Open song in dedicated tracker window");
268
269 ImGui::SameLine();
270 if (ImGui::Button(ICON_MD_PIANO " Open Piano Roll")) {
273 }
274 if (ImGui::IsItemHovered())
275 ImGui::SetTooltip("Open piano roll view for this song");
276 }
277
279 if (!music_player_)
280 return;
281
282 if (!ImGui::CollapsingHeader(ICON_MD_BUG_REPORT " Debug Controls"))
283 return;
284
285 ImGui::Indent();
286
287 // Pause updates checkbox
288 ImGui::Checkbox("Pause Updates", &debug_paused_);
289 ImGui::SameLine();
290 if (ImGui::Button("Snapshot")) {
291 // Force capture current values
292 debug_paused_ = true;
293 }
294 ImGui::SameLine();
295 ImGui::TextDisabled("(Freeze display to read values)");
296
297 // Capture current state (unless paused)
298 if (!debug_paused_) {
303
304 // Track statistics using wall-clock time for accuracy
306 auto now = std::chrono::steady_clock::now();
307
308 // Initialize on first call
309 if (last_stats_time_.time_since_epoch().count() == 0) {
310 last_stats_time_ = now;
313 }
314
315 auto elapsed =
316 std::chrono::duration<double>(now - last_stats_time_).count();
317
318 // Update stats every 0.5 seconds
319 if (elapsed >= 0.5) {
320 uint64_t cycle_delta = cached_apu_.cycles - last_cycles_for_rate_;
321 int32_t queue_delta =
322 static_cast<int32_t>(cached_audio_.queued_frames) -
323 static_cast<int32_t>(last_queued_for_rate_);
324
325 // Calculate actual rates based on elapsed wall-clock time
326 avg_cycle_rate_ = static_cast<uint64_t>(cycle_delta / elapsed);
327 avg_queue_delta_ = static_cast<int32_t>(queue_delta / elapsed);
328
329 // Reset for next measurement
330 last_stats_time_ = now;
333 }
334 } else {
335 // Reset when stopped
336 last_stats_time_ = std::chrono::steady_clock::time_point();
337 }
338 }
339
340 // === Quick Summary (always visible) ===
341 ImGui::Separator();
342 ImVec4 status_color = cached_audio_.is_playing ? gui::GetSuccessColor()
344 ImGui::TextColored(status_color,
345 cached_audio_.is_playing ? "PLAYING" : "STOPPED");
346 ImGui::SameLine();
347 ImGui::Text("| Queue: %u frames", cached_audio_.queued_frames);
348 ImGui::SameLine();
349 ImGui::Text("| DSP: %u/2048", cached_dsp_.sample_offset);
350
351 // Queue trend indicator
352 ImGui::SameLine();
353 if (avg_queue_delta_ > 50) {
354 ImGui::TextColored(gui::GetErrorColor(),
355 ICON_MD_TRENDING_UP " GROWING (too fast!)");
356 } else if (avg_queue_delta_ < -50) {
357 ImGui::TextColored(gui::GetWarningColor(),
358 ICON_MD_TRENDING_DOWN " DRAINING");
359 } else {
360 ImGui::TextColored(gui::GetSuccessColor(),
361 ICON_MD_TRENDING_FLAT " STABLE");
362 }
363
364 // Cycle rate check (should be ~1,024,000/sec)
365 if (avg_cycle_rate_ > 0) {
366 float rate_ratio = avg_cycle_rate_ / 1024000.0f;
367 ImGui::Text("APU Rate: %.2fx expected", rate_ratio);
368 if (rate_ratio > 1.1f) {
369 ImGui::SameLine();
370 ImGui::TextColored(gui::GetErrorColor(), "(APU running too fast!)");
371 }
372 }
373
374 ImGui::Separator();
375
376 // === DSP Buffer Status ===
377 if (ImGui::TreeNode("DSP Buffer")) {
378 auto& dsp = cached_dsp_;
379
380 ImGui::Text("Sample Offset: %u / 2048", dsp.sample_offset);
381 ImGui::Text("Frame Boundary: %u", dsp.frame_boundary);
382
383 // Buffer fill progress bar
384 float fill = dsp.sample_offset / 2048.0f;
385 char overlay[32];
386 snprintf(overlay, sizeof(overlay), "%.1f%%", fill * 100.0f);
387 ImGui::ProgressBar(fill, ImVec2(-1, 0), overlay);
388
389 // Drift indicator
390 int32_t drift = static_cast<int32_t>(dsp.sample_offset) -
391 static_cast<int32_t>(dsp.frame_boundary);
392 ImVec4 drift_color = (std::abs(drift) > 100) ? gui::GetErrorColor()
394 ImGui::TextColored(drift_color, "Drift: %+d samples", drift);
395
396 ImGui::Text("Master Vol: L=%d R=%d", dsp.master_vol_l, dsp.master_vol_r);
397
398 // Status flags
399 if (dsp.mute) {
400 ImGui::TextColored(gui::GetWarningColor(), ICON_MD_VOLUME_OFF " MUTED");
401 ImGui::SameLine();
402 }
403 if (dsp.reset) {
404 ImGui::TextColored(gui::GetErrorColor(), ICON_MD_RESTART_ALT " RESET");
405 ImGui::SameLine();
406 }
407 if (dsp.echo_enabled) {
408 ImGui::TextColored(gui::GetInfoColor(),
409 ICON_MD_SURROUND_SOUND " Echo (delay=%u)",
410 dsp.echo_delay);
411 }
412
413 ImGui::TreePop();
414 }
415
416 // === Audio Queue Status ===
417 if (ImGui::TreeNode("Audio Queue")) {
418 auto& audio = cached_audio_;
419
420 // Status indicator
421 if (audio.is_playing) {
422 ImGui::TextColored(gui::GetSuccessColor(),
423 ICON_MD_PLAY_CIRCLE " Playing");
424 } else {
425 ImGui::TextColored(gui::GetDisabledColor(),
426 ICON_MD_STOP_CIRCLE " Stopped");
427 }
428
429 ImGui::Text("Queued: %u frames (%u bytes)", audio.queued_frames,
430 audio.queued_bytes);
431 ImGui::Text("Sample Rate: %d Hz", audio.sample_rate);
432 ImGui::Text("Backend: %s", audio.backend_name.c_str());
433
434 // Underrun warning
435 if (audio.has_underrun) {
436 ImGui::TextColored(gui::GetErrorColor(),
437 ICON_MD_WARNING " UNDERRUN DETECTED");
438 }
439
440 // Queue level indicator
441 float queue_level = audio.queued_frames / 6000.0f; // ~100ms worth
442 queue_level = std::clamp(queue_level, 0.0f, 1.0f);
443 ImVec4 queue_color =
444 (queue_level < 0.2f) ? gui::GetErrorColor() : gui::GetSuccessColor();
445 {
446 gui::StyleColorGuard queue_guard(ImGuiCol_PlotHistogram, queue_color);
447 ImGui::ProgressBar(queue_level, ImVec2(-1, 0), "Queue Level");
448 }
449
450 ImGui::TreePop();
451 }
452
453 // === APU Timing ===
454 if (ImGui::TreeNode("APU Timing")) {
455 auto& apu = cached_apu_;
456
457 ImGui::Text("Cycles: %llu", static_cast<unsigned long long>(apu.cycles));
458
459 // Timers in a table
460 if (ImGui::BeginTable("Timers", 4, ImGuiTableFlags_Borders)) {
461 ImGui::TableSetupColumn("Timer");
462 ImGui::TableSetupColumn("Enabled");
463 ImGui::TableSetupColumn("Counter");
464 ImGui::TableSetupColumn("Target");
465 ImGui::TableHeadersRow();
466
467 // Timer 0
468 ImGui::TableNextRow();
469 ImGui::TableNextColumn();
470 ImGui::Text("T0");
471 ImGui::TableNextColumn();
472 ImGui::TextColored(apu.timer0_enabled ? gui::GetSuccessColor()
474 apu.timer0_enabled ? "ON" : "off");
475 ImGui::TableNextColumn();
476 ImGui::Text("%u", apu.timer0_counter);
477 ImGui::TableNextColumn();
478 ImGui::Text("%u", apu.timer0_target);
479
480 // Timer 1
481 ImGui::TableNextRow();
482 ImGui::TableNextColumn();
483 ImGui::Text("T1");
484 ImGui::TableNextColumn();
485 ImGui::TextColored(apu.timer1_enabled ? gui::GetSuccessColor()
487 apu.timer1_enabled ? "ON" : "off");
488 ImGui::TableNextColumn();
489 ImGui::Text("%u", apu.timer1_counter);
490 ImGui::TableNextColumn();
491 ImGui::Text("%u", apu.timer1_target);
492
493 // Timer 2
494 ImGui::TableNextRow();
495 ImGui::TableNextColumn();
496 ImGui::Text("T2");
497 ImGui::TableNextColumn();
498 ImGui::TextColored(apu.timer2_enabled ? gui::GetSuccessColor()
500 apu.timer2_enabled ? "ON" : "off");
501 ImGui::TableNextColumn();
502 ImGui::Text("%u", apu.timer2_counter);
503 ImGui::TableNextColumn();
504 ImGui::Text("%u", apu.timer2_target);
505
506 ImGui::EndTable();
507 }
508
509 // Port state
510 ImGui::Text("Ports IN: [0]=%02X [1]=%02X", apu.port0_in, apu.port1_in);
511 ImGui::Text("Ports OUT: [0]=%02X [1]=%02X", apu.port0_out, apu.port1_out);
512
513 ImGui::TreePop();
514 }
515
516 // === Channel Overview ===
517 if (ImGui::TreeNode("Channels")) {
518 auto& channels = cached_channels_;
519
520 ImGui::Text("Key Status:");
521 ImGui::SameLine();
522 for (int i = 0; i < 8; i++) {
523 ImVec4 color = channels[i].key_on ? gui::GetSuccessColor()
525 ImGui::TextColored(color, "%d", i);
526 if (i < 7)
527 ImGui::SameLine();
528 }
529
530 // Detailed channel info
531 if (ImGui::BeginTable("ChannelDetails", 6,
532 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
533 ImGui::TableSetupColumn("Ch", ImGuiTableColumnFlags_WidthFixed, 25);
534 ImGui::TableSetupColumn("Key");
535 ImGui::TableSetupColumn("Sample");
536 ImGui::TableSetupColumn("Pitch");
537 ImGui::TableSetupColumn("Vol L/R");
538 ImGui::TableSetupColumn("ADSR");
539 ImGui::TableHeadersRow();
540
541 const char* adsr_names[] = {"Atk", "Dec", "Sus", "Rel"};
542 for (int i = 0; i < 8; i++) {
543 ImGui::TableNextRow();
544 ImGui::TableNextColumn();
545 ImGui::Text("%d", i);
546 ImGui::TableNextColumn();
547 ImGui::TextColored(channels[i].key_on ? gui::GetSuccessColor()
549 channels[i].key_on ? "ON" : "--");
550 ImGui::TableNextColumn();
551 ImGui::Text("%02X", channels[i].sample_index);
552 ImGui::TableNextColumn();
553 ImGui::Text("%04X", channels[i].pitch);
554 ImGui::TableNextColumn();
555 ImGui::Text("%02X/%02X", channels[i].volume_l, channels[i].volume_r);
556 ImGui::TableNextColumn();
557 int state = channels[i].adsr_state & 0x03;
558 ImGui::Text("%s", adsr_names[state]);
559 }
560
561 ImGui::EndTable();
562 }
563
564 ImGui::TreePop();
565 }
566
567 // === Action Buttons ===
568 ImGui::Separator();
569 ImGui::Text("Actions:");
570
571 if (ImGui::Button(ICON_MD_CLEAR_ALL " Clear Queue")) {
573 }
574 if (ImGui::IsItemHovered())
575 ImGui::SetTooltip("Clear SDL audio queue immediately");
576
577 ImGui::SameLine();
578 if (ImGui::Button(ICON_MD_REFRESH " Reset DSP")) {
580 }
581 if (ImGui::IsItemHovered())
582 ImGui::SetTooltip("Reset DSP sample ring buffer");
583
584 ImGui::SameLine();
585 if (ImGui::Button(ICON_MD_SKIP_NEXT " NewFrame")) {
587 }
588 if (ImGui::IsItemHovered())
589 ImGui::SetTooltip("Force DSP NewFrame() call");
590
591 ImGui::SameLine();
592 if (ImGui::Button(ICON_MD_REPLAY " Reinit Audio")) {
594 }
595 if (ImGui::IsItemHovered())
596 ImGui::SetTooltip("Full audio system reinitialization");
597
598 ImGui::Unindent();
599 }
600
602 int* current_song_index_ = nullptr;
605
606 std::function<void(int)> on_open_song_;
607 std::function<void(int)> on_open_piano_roll_;
608
609 // Debug state
610 bool debug_paused_ = false;
614 std::array<music::ChannelState, 8> cached_channels_;
615 int32_t avg_queue_delta_ = 0;
616 uint64_t avg_cycle_rate_ = 0;
617
618 // Wall-clock timing for rate measurement
619 std::chrono::steady_clock::time_point last_stats_time_;
622};
623
624} // namespace editor
625} // namespace yaze
626
627#endif // YAZE_APP_EDITOR_MUSIC_PANELS_MUSIC_PLAYBACK_CONTROL_PANEL_H_
WindowContent for music playback controls and status display.
void SetOnOpenPianoRoll(std::function< void(int)> callback)
int GetPriority() const override
Get display priority for menu ordering.
std::string GetIcon() const override
Material Design icon for this panel.
std::string GetEditorCategory() const override
Editor category this panel belongs to.
void SetOnOpenSong(std::function< void(int)> callback)
void Draw(bool *p_open) override
Draw the panel content.
std::chrono::steady_clock::time_point last_stats_time_
std::string GetId() const override
Unique identifier for this panel.
std::string GetDisplayName() const override
Human-readable name shown in menus and title bars.
MusicPlaybackControlPanel(zelda3::music::MusicBank *music_bank, int *current_song_index, music::MusicPlayer *music_player)
std::array< music::ChannelState, 8 > cached_channels_
Base interface for all logical window content components.
Handles audio playback for the music editor using the SNES APU emulator.
ApuDebugStatus GetApuStatus() const
Get APU timing diagnostic status.
void Stop()
Stop playback completely.
void ReinitAudio()
Reinitialize the audio system.
void SetPlaybackSpeed(float speed)
Set the playback speed (0.25x to 2.0x).
void ForceNewFrame()
Force a DSP NewFrame() call.
void SetVolume(float volume)
Set the master volume (0.0 to 1.0).
void Pause()
Pause the current playback.
AudioQueueStatus GetAudioQueueStatus() const
Get audio queue diagnostic status.
std::array< ChannelState, 8 > GetChannelStates() const
void PlaySong(int song_index)
Start playing a song by index.
DspDebugStatus GetDspStatus() const
Get DSP buffer diagnostic status.
void Resume()
Resume paused playback.
bool IsAudioReady() const
Check if the audio system is ready for playback.
PlaybackState GetState() const
void ResetDspBuffer()
Reset the DSP sample buffer.
void ClearAudioQueue()
Clear the audio queue (stops sound immediately).
RAII guard for ImGui style colors.
Definition style_guard.h:27
Manages the collection of songs, instruments, and samples from a ROM.
Definition music_bank.h:27
MusicSong * GetSong(int index)
Get a song by index.
#define ICON_MD_PAUSE_CIRCLE
Definition icons.h:1390
#define ICON_MD_PAUSE
Definition icons.h:1389
#define ICON_MD_PIANO
Definition icons.h:1462
#define ICON_MD_WARNING
Definition icons.h:2123
#define ICON_MD_VOLUME_UP
Definition icons.h:2111
#define ICON_MD_TRENDING_DOWN
Definition icons.h:2013
#define ICON_MD_TRENDING_UP
Definition icons.h:2016
#define ICON_MD_PLAY_ARROW
Definition icons.h:1479
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_STOP
Definition icons.h:1862
#define ICON_MD_BUG_REPORT
Definition icons.h:327
#define ICON_MD_GRAPHIC_EQ
Definition icons.h:890
#define ICON_MD_EDIT
Definition icons.h:645
#define ICON_MD_SPEED
Definition icons.h:1817
#define ICON_MD_REPLAY
Definition icons.h:1588
#define ICON_MD_STOP_CIRCLE
Definition icons.h:1863
#define ICON_MD_CLEAR_ALL
Definition icons.h:417
#define ICON_MD_KEYBOARD
Definition icons.h:1028
#define ICON_MD_PLAY_CIRCLE
Definition icons.h:1480
#define ICON_MD_SKIP_NEXT
Definition icons.h:1773
#define ICON_MD_SURROUND_SOUND
Definition icons.h:1894
#define ICON_MD_OPEN_IN_NEW
Definition icons.h:1354
#define ICON_MD_VOLUME_OFF
Definition icons.h:2110
#define ICON_MD_RESTART_ALT
Definition icons.h:1602
#define ICON_MD_TRENDING_FLAT
Definition icons.h:2014
bool SliderIntWheel(const char *label, int *v, int v_min, int v_max, const char *format, int wheel_step, ImGuiSliderFlags flags)
Definition input.cc:776
ImVec4 GetSuccessColor()
Definition ui_helpers.cc:48
bool SliderFloatWheel(const char *label, float *v, float v_min, float v_max, const char *format, float wheel_step, ImGuiSliderFlags flags)
Definition input.cc:759
ButtonColorSet GetSuccessButtonColors()
ImVec4 GetDisabledColor()
Definition ui_helpers.cc:73
ImVec4 GetErrorColor()
Definition ui_helpers.cc:58
ImVec4 GetWarningColor()
Definition ui_helpers.cc:53
ImVec4 GetInfoColor()
Definition ui_helpers.cc:63
APU timing diagnostic status for debug UI.
Audio queue diagnostic status for debug UI.
DSP buffer diagnostic status for debug UI.
Represents the current playback state of the music player.