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