yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
music_editor.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_MUSIC_EDITOR_H
2#define YAZE_APP_EDITOR_MUSIC_EDITOR_H
3
4#include <chrono>
5#include <memory>
6#include <optional>
7#include <string>
8#include <unordered_map>
9
10#include "absl/status/statusor.h"
12#include "app/editor/editor.h"
21#include "imgui/imgui.h"
22#include "rom/rom.h"
27
28namespace yaze {
29
30// Forward declaration
31namespace emu {
32class Emulator;
33namespace audio {
34class IAudioBackend;
35struct AudioConfig;
36} // namespace audio
37} // namespace emu
38
39namespace project {
40struct YazeProject;
41}
42
43namespace editor {
44
45// TODO(user): Remove this when MusicBank provides song names
46static const char* kGameSongs[] = {"Title",
47 "Light World",
48 "Beginning",
49 "Rabbit",
50 "Forest",
51 "Intro",
52 "Town",
53 "Warp",
54 "Dark world",
55 "Master sword",
56 "File select",
57 "Soldier",
58 "Mountain",
59 "Shop",
60 "Fanfare",
61 "Castle",
62 "Palace (Pendant)",
63 "Cave (Same as Secret Way)",
64 "Clear (Dungeon end)",
65 "Church",
66 "Boss",
67 "Dungeon (Crystal)",
68 "Psychic",
69 "Secret Way (Same as Cave)",
70 "Rescue",
71 "Crystal",
72 "Fountain",
73 "Pyramid",
74 "Kill Agahnim",
75 "Ganon Room",
76 "Last Boss"};
77
78static constexpr absl::string_view kSongNotes[] = {
79 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C",
80 "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C"};
81
82const ImGuiTableFlags toolset_table_flags_ = ImGuiTableFlags_SizingFixedFit;
83const ImGuiTableFlags music_editor_flags_ = ImGuiTableFlags_SizingFixedFit |
84 ImGuiTableFlags_Resizable |
85 ImGuiTableFlags_Reorderable;
90class MusicEditor : public Editor {
91 public:
92 explicit MusicEditor(Rom* rom = nullptr) : rom_(rom) {
94 }
95
96 void SetDependencies(const EditorDependencies& deps) override;
97
98 void Initialize() override;
99 absl::Status Load() override;
100 absl::Status Save() override;
101 absl::Status Update() override;
102 absl::Status Cut() override;
103 absl::Status Copy() override;
104 absl::Status Paste() override;
105 absl::Status Undo() override;
106 absl::Status Redo() override;
107 absl::Status Find() override { return absl::UnimplementedError("Find"); }
108 // A pending tracker edit is committed to history by Undo(), so it counts.
109 bool CanUndo() const override {
110 return pending_undo_before_.has_value() || undo_manager_.CanUndo();
111 }
112 // Copy/Paste are unimplemented (see MusicEditor::Copy/Paste).
113 bool CanCut() const override { return false; }
114 bool CanCopy() const override { return false; }
115 bool CanPaste() const override { return false; }
116
117 // Set the ROM pointer
118 void set_rom(Rom* rom) { rom_ = rom; }
119
120 // Get the ROM pointer
121 Rom* rom() const { return rom_; }
122
123 // Emulator integration for live audio playback
125 emu::Emulator* emulator() const { return emulator_; }
126
128
129 // Scoped editor actions (for ShortcutManager)
130 void TogglePlayPause();
131 void StopPlayback();
132 void SpeedUp(float delta = 0.1f);
133 void SlowDown(float delta = 0.1f);
134
135 // API for sub-views
136
137 // Song window management (like dungeon rooms)
138 void OpenSong(int song_index);
139 void FocusSong(int song_index);
140
141 private:
142 // UI Drawing Methods
143 void DrawSongTrackerWindow(int song_index);
144 void DrawPlaybackControl(); // Playback control panel
145 void DrawTrackerView(); // Legacy tracker view
146 void DrawPianoRollView();
148 void DrawSampleEditor();
149 void DrawSongBrowser();
150 void DrawToolset();
151 void DrawChannelOverview();
152 absl::StatusOr<bool> RestoreMusicState();
153 absl::Status PersistMusicState(const char* reason = nullptr);
154 void MarkMusicDirty();
155
156 // Playback Control
157 // Delegated to music_player_
158
160
161 // New Data Model
168
169 // Undo/Redo (delegates to undo_manager_ from Editor base class)
170 void PushUndoState();
171 void PushUndoState(int song_index);
172 void FinalizePendingUndo();
173 std::optional<zelda3::music::MusicSong> pending_undo_before_;
175
176 // Note: APU requires ROM memory, will be initialized when needed
177
178 // UI State
179 int current_song_index_ = 0; // Selected song in browser (UI selection)
183 std::vector<bool> channel_muted_ = std::vector<bool>(8, false);
184 std::vector<bool> channel_soloed_ = std::vector<bool>(8, false);
185 std::vector<std::string> song_names_;
186
187 // Accessors for UI Views
189 void set_current_channel(int channel) {
190 if (channel >= 0 && channel < 8)
191 current_channel_index_ = channel;
192 }
193
194 ImGuiTableFlags music_editor_flags_ =
195 ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter |
196 ImGuiTableFlags_BordersV | ImGuiTableFlags_SizingFixedFit;
197
198 ImGuiTableFlags toolset_table_flags_ =
199 ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersOuter |
200 ImGuiTableFlags_BordersV | ImGuiTableFlags_PadOuterX;
201
203 emu::Emulator* emulator_ = nullptr; // For live audio playback
205
206 // Single shared audio backend - owned here and shared with emulators
207 // This avoids the dual-backend bug where two SDL audio devices conflict
208 std::unique_ptr<emu::audio::IAudioBackend> audio_backend_;
212 bool music_dirty_ = false;
215 std::chrono::steady_clock::time_point last_music_persist_;
216
217 // Per-song tracker windows (like dungeon room cards)
218 ImVector<int> active_songs_; // Song indices that are currently open
219 std::unordered_map<int, std::shared_ptr<gui::PanelWindow>> song_cards_;
220 std::unordered_map<int, std::unique_ptr<editor::music::TrackerView>>
223 std::shared_ptr<gui::PanelWindow> card;
224 std::unique_ptr<editor::music::PianoRollView> view;
225 bool* visible_flag = nullptr;
226 };
227 std::unordered_map<int, SongPianoRollWindow> song_piano_rolls_;
228
229 // Docking class for song windows to dock together
230 ImGuiWindowClass song_window_class_;
231
232 void OpenSongPianoRoll(int song_index);
233
234 // ASM export/import
235 void ExportSongToAsm(int song_index);
236 void ImportSongFromAsm(int song_index);
237 bool ImportAsmBufferToSong(int song_index);
238 void DrawAsmPopups();
239
240 std::string asm_buffer_; // Buffer for ASM text
241 bool show_asm_export_popup_ = false; // Show export dialog
242 bool show_asm_import_popup_ = false; // Show import dialog
243 int asm_import_target_index_ = -1; // Song index for import target
244 std::string asm_import_error_; // Last ASM import error (UI)
245 // Segment seeking
246 void SeekToSegment(int segment_index);
247
248 std::unique_ptr<editor::music::MusicPlayer> music_player_;
249
250 // Note: WindowContent instances are owned by WorkspaceWindowManager after registration
251};
252
253} // namespace editor
254} // namespace yaze
255
256#endif
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:49
Text editor for modifying assembly code.
Interface for editor classes.
Definition editor.h:249
UndoManager undo_manager_
Definition editor.h:371
project::YazeProject * project() const
Definition editor.h:358
EditorType type_
Definition editor.h:369
A class for editing music data in a Rom.
absl::Status Find() override
std::unordered_map< int, std::unique_ptr< editor::music::TrackerView > > song_trackers_
void FocusSong(int song_index)
std::unique_ptr< emu::audio::IAudioBackend > audio_backend_
ImVector< int > active_songs_
std::vector< bool > channel_soloed_
void SlowDown(float delta=0.1f)
void DrawSongTrackerWindow(int song_index)
emu::Emulator * emulator_
bool CanCopy() const override
std::unordered_map< int, std::shared_ptr< gui::PanelWindow > > song_cards_
std::optional< zelda3::music::MusicSong > pending_undo_before_
absl::Status Paste() override
std::vector< bool > channel_muted_
zelda3::music::MusicBank music_bank_
std::unordered_map< int, SongPianoRollWindow > song_piano_rolls_
void SetProject(project::YazeProject *project)
void Initialize() override
void OpenSong(int song_index)
emu::Emulator * emulator() const
void ExportSongToAsm(int song_index)
editor::music::SampleEditorView sample_editor_view_
absl::Status Save() override
absl::Status Cut() override
bool CanCut() const override
void OpenSongPianoRoll(int song_index)
absl::Status Load() override
void SetDependencies(const EditorDependencies &deps) override
void ImportSongFromAsm(int song_index)
absl::StatusOr< bool > RestoreMusicState()
absl::Status Copy() override
void SpeedUp(float delta=0.1f)
absl::Status PersistMusicState(const char *reason=nullptr)
absl::Status Update() override
editor::music::InstrumentEditorView instrument_editor_view_
bool CanUndo() const override
std::unique_ptr< editor::music::MusicPlayer > music_player_
void set_emulator(emu::Emulator *emulator)
ImGuiTableFlags music_editor_flags_
absl::Status Undo() override
absl::Status Redo() override
ImGuiTableFlags toolset_table_flags_
std::vector< std::string > song_names_
std::chrono::steady_clock::time_point last_music_persist_
void set_current_channel(int channel)
AssemblyEditor assembly_editor_
bool ImportAsmBufferToSong(int song_index)
project::YazeProject * project_
MusicEditor(Rom *rom=nullptr)
bool CanPaste() const override
void SeekToSegment(int segment_index)
editor::music::TrackerView tracker_view_
editor::music::SongBrowserView song_browser_view_
editor::music::PianoRollView piano_roll_view_
ImGuiWindowClass song_window_class_
Editor for SNES instruments (ADSR, Gain, Samples).
UI component for displaying and editing music tracks as a piano roll.
UI component for browsing and managing songs.
UI component for displaying and editing music tracks.
A class for emulating and debugging SNES games.
Definition emulator.h:41
Abstract audio backend interface.
Manages the collection of songs, instruments, and samples from a ROM.
Definition music_bank.h:27
const ImGuiTableFlags music_editor_flags_
const ImGuiTableFlags toolset_table_flags_
Unified dependency container for all editor types.
Definition editor.h:170
std::unique_ptr< editor::music::PianoRollView > view
std::shared_ptr< gui::PanelWindow > card
Modern project structure with comprehensive settings consolidation.
Definition project.h:287