2026-10-26 23:07:03 +01:00
|
|
|
#ifndef XTC_MAIN_WINDOW_HPP
|
|
|
|
|
#define XTC_MAIN_WINDOW_HPP
|
2026-10-26 22:51:25 +01:00
|
|
|
|
|
|
|
|
#include <FL/Fl_Double_Window.H>
|
2026-10-26 23:55:35 +01:00
|
|
|
#include <memory>
|
2026-10-27 00:10:45 +01:00
|
|
|
#include <string>
|
|
|
|
|
#include "xtc/xtc_project.h"
|
2026-10-26 23:40:28 +01:00
|
|
|
#include "xtc/xtc_backend.h"
|
2026-10-27 01:06:57 +01:00
|
|
|
#include "xtc/xtc_mixer.h"
|
2026-10-26 23:40:28 +01:00
|
|
|
|
2026-10-26 23:55:35 +01:00
|
|
|
class GraphWidget;
|
2026-10-27 01:06:57 +01:00
|
|
|
class MixerWidget;
|
2026-10-27 00:53:41 +01:00
|
|
|
class PianoRollWidget;
|
2026-10-27 00:10:45 +01:00
|
|
|
class SequencerWidget;
|
2026-10-26 23:40:28 +01:00
|
|
|
class Fl_Box;
|
|
|
|
|
class Fl_Button;
|
|
|
|
|
class Fl_Tabs;
|
2026-10-26 22:51:25 +01:00
|
|
|
|
|
|
|
|
class MainWindow : public Fl_Double_Window {
|
|
|
|
|
public:
|
2026-10-27 00:10:45 +01:00
|
|
|
explicit MainWindow(bool prompt_unsaved = true);
|
2026-10-26 23:40:28 +01:00
|
|
|
~MainWindow() override;
|
|
|
|
|
MainWindow(const MainWindow &) = delete;
|
|
|
|
|
MainWindow &operator=(const MainWindow &) = delete;
|
|
|
|
|
using Fl_Double_Window::show;
|
|
|
|
|
int handle(int event) override;
|
|
|
|
|
|
2026-10-27 01:06:57 +01:00
|
|
|
xtc_result undo(bool redo = false);
|
|
|
|
|
MixerWidget *mixer() const { return mixer_; }
|
2026-10-27 00:53:41 +01:00
|
|
|
xtc_result open_piano_roll();
|
|
|
|
|
PianoRollWidget *piano_roll() const { return piano_; }
|
2026-10-27 00:31:03 +01:00
|
|
|
xtc_result import_audio(const char *path);
|
|
|
|
|
xtc_result record_audio(const char *path);
|
2026-10-27 00:10:45 +01:00
|
|
|
xtc_result save_project(const char *path);
|
|
|
|
|
xtc_result open_project(const char *path);
|
2026-10-26 23:40:28 +01:00
|
|
|
private:
|
2026-10-27 01:06:57 +01:00
|
|
|
MixerWidget *mixer_ = nullptr;
|
|
|
|
|
std::unique_ptr<xtc_history, decltype(&xtc_history_destroy)> history_{nullptr, xtc_history_destroy};
|
|
|
|
|
static void history_callback(Fl_Widget *, void *);
|
2026-10-27 00:10:45 +01:00
|
|
|
std::unique_ptr<xtc_project, decltype(&xtc_project_destroy)> project_{nullptr, xtc_project_destroy};
|
2026-10-27 00:53:41 +01:00
|
|
|
std::unique_ptr<Fl_Double_Window> piano_window_;
|
|
|
|
|
PianoRollWidget *piano_ = nullptr;
|
|
|
|
|
static void piano_callback(Fl_Widget *, void *context);
|
|
|
|
|
static void panic_callback(Fl_Widget *, void *context);
|
2026-10-27 00:10:45 +01:00
|
|
|
SequencerWidget *sequencer_ = nullptr;
|
2026-10-27 00:31:03 +01:00
|
|
|
xtc_recorder *recorder_ = nullptr;
|
|
|
|
|
std::string recording_path_;
|
|
|
|
|
uint64_t recording_tick_ = 0, recording_track_ = UINT64_MAX;
|
|
|
|
|
void finish_recording();
|
|
|
|
|
static xtc_result before_arrangement_edit(void *context);
|
|
|
|
|
static void audio_file_callback(Fl_Widget *, void *context);
|
2026-10-27 00:10:45 +01:00
|
|
|
bool dirty_ = false, prompt_unsaved_ = true;
|
|
|
|
|
std::string path_;
|
|
|
|
|
bool discard_changes();
|
|
|
|
|
void mark_dirty();
|
2026-10-27 01:06:57 +01:00
|
|
|
xtc_result install_project(xtc_project *candidate, bool reset_history = true);
|
2026-10-27 00:10:45 +01:00
|
|
|
static xtc_result seek(void *context, uint64_t tick);
|
|
|
|
|
static void file_callback(Fl_Widget *, void *context);
|
2026-10-26 23:55:35 +01:00
|
|
|
GraphWidget *graph_widget_ = nullptr;
|
|
|
|
|
Fl_Box *graph_state_ = nullptr;
|
2026-10-26 23:40:28 +01:00
|
|
|
xtc_backend *backend_ = nullptr;
|
|
|
|
|
bool ready_ = false;
|
|
|
|
|
bool running_ = false;
|
|
|
|
|
bool closing_ = false;
|
2026-10-27 00:31:03 +01:00
|
|
|
Fl_Button *record_ = nullptr;
|
2026-10-26 23:40:28 +01:00
|
|
|
Fl_Button *play_ = nullptr;
|
|
|
|
|
Fl_Button *stop_ = nullptr;
|
|
|
|
|
Fl_Box *indicator_ = nullptr;
|
|
|
|
|
Fl_Box *status_ = nullptr;
|
|
|
|
|
Fl_Box *error_ = nullptr;
|
|
|
|
|
Fl_Tabs *tabs_ = nullptr;
|
|
|
|
|
|
2026-10-26 23:55:35 +01:00
|
|
|
static xtc_result edit_graph(void *context, const xtc_graph_edit &edit, size_t *out_added_id);
|
2026-10-26 23:40:28 +01:00
|
|
|
void open_backend();
|
|
|
|
|
void start_engine();
|
|
|
|
|
void stop_engine();
|
|
|
|
|
void reconnect_engine();
|
|
|
|
|
void refresh_status();
|
|
|
|
|
bool close_window();
|
|
|
|
|
void report_error(const char *operation, xtc_result result);
|
|
|
|
|
static void play_callback(Fl_Widget *, void *context);
|
|
|
|
|
static void stop_callback(Fl_Widget *, void *context);
|
|
|
|
|
static void reconnect_callback(Fl_Widget *, void *context);
|
|
|
|
|
static void close_callback(Fl_Widget *, void *context);
|
|
|
|
|
static void view_callback(Fl_Widget *widget, void *view);
|
|
|
|
|
static void about_callback(Fl_Widget *, void *);
|
|
|
|
|
static void timer_callback(void *context);
|
2026-10-26 22:51:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|