554 lines
24 KiB
C++
554 lines
24 KiB
C++
#ifndef XTC_MAIN_WINDOW_HPP
|
|
#define XTC_MAIN_WINDOW_HPP
|
|
|
|
#include <FL/Fl_Double_Window.H>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <string>
|
|
#include "xtc/xtc_project.h"
|
|
#include "xtc/xtc_sample.h"
|
|
#include "xtc/xtc_editing.h"
|
|
#include "xtc/xtc_backend.h"
|
|
#include "xtc/xtc_mixer.h"
|
|
#include "xtc/xtc_plugin.h"
|
|
#include "xtc/xtc_tempo.h"
|
|
#include "xtc/xtc_control.h"
|
|
#include "xtc/xtc_settings.h"
|
|
|
|
class GraphWidget;
|
|
class MixerWidget;
|
|
class PianoRollWidget;
|
|
class SequencerWidget;
|
|
class Fl_Box;
|
|
class Fl_Group;
|
|
class Fl_Button;
|
|
class Fl_Tabs;
|
|
class Fl_Menu_Bar;
|
|
class Fl_Choice;
|
|
class Fl_Value_Slider;
|
|
class Fl_Value_Input;
|
|
class Fl_Scroll;
|
|
class Fl_Check_Button;
|
|
|
|
class TrackInsertsPanel;
|
|
class MainWindow : public Fl_Double_Window {
|
|
public:
|
|
xtc_result set_track_chain(uint64_t track,const xtc_track_chain &chain);
|
|
xtc_result add_track_effect(uint64_t track,const char *file,unsigned int index);
|
|
TrackInsertsPanel *track_inserts() const {return track_inserts_;}
|
|
void show_track_inspector(bool visible);
|
|
xtc_result open_track_inserts(uint64_t track=UINT64_MAX);
|
|
/* One undoable candidate edit. MIDI also adds a one-bar clip at the cursor.
|
|
* Preparation stops/resets transport; recording and failed candidates retain
|
|
* the current document. No engine/model changes happen in audio callbacks. */
|
|
xtc_result create_track(bool midi);
|
|
xtc_result set_tempo(unsigned int milli_bpm);
|
|
xtc_result tap_tempo(double seconds);
|
|
xtc_result collect_project(const char *directory);
|
|
xtc_result navigate_marker(int direction);
|
|
xtc_result loop_section();
|
|
void show_commands();
|
|
xtc_result mix_snapshot(unsigned int slot,bool capture);
|
|
/* Reparent the existing controls on the UI thread; closing a panel docks it. */
|
|
void detach_editor(unsigned int index,bool detached); /* 0 sequencer, 1 graph */
|
|
void detach_piano(bool detached);
|
|
void reset_layout();
|
|
Fl_Double_Window *editor_window(unsigned int index) const {return index<2 ? editors_[index].window.get() : nullptr;}
|
|
void layout_transport();
|
|
void resize(int x,int y,int width,int height) override;
|
|
void detach_transport(bool detached);
|
|
void detach_mixer(bool detached);
|
|
Fl_Double_Window *transport_window() const { return transport_window_.get(); }
|
|
Fl_Double_Window *mixer_window() const { return mixer_window_.get(); }
|
|
int panel_shortcut(int event);
|
|
|
|
void fit_song();
|
|
const xtc_settings &settings() const { return settings_; }
|
|
xtc_result apply_preferences(const xtc_settings &settings);
|
|
void show_preferences();
|
|
std::vector<std::string> midi_devices(bool input);
|
|
xtc_result start_configured_backend();
|
|
xtc_result save_preferences();
|
|
xtc_result set_loop(uint64_t start,uint64_t end,bool enabled);
|
|
Fl_Widget *velocity_lane() const { return velocity_lane_; }
|
|
/* Control-thread plugin commands, transactional model adoption. */
|
|
xtc_result assign_instrument(uint64_t track, const char *path, unsigned int index);
|
|
xtc_result adopt_sample_copy(uint64_t clip,const xtc_sample *sample,const char *path);
|
|
xtc_result slice_sample_clip(uint64_t clip,unsigned int rate,const std::vector<size_t> &positions);
|
|
xtc_result trim_sample_clip(uint64_t clip,unsigned int rate,size_t begin,size_t end);
|
|
xtc_result open_sample_editor();
|
|
void export_audio();
|
|
xtc_result export_midi_clip(const char *path);
|
|
void export_midi_dialog();
|
|
xtc_result load_sampler(uint64_t track, const char *path);
|
|
xtc_result set_instrument_spec(uint64_t track, const xtc_plugin_spec &spec);
|
|
xtc_result select_live_instrument(uint64_t track);
|
|
static void instrument_callback(Fl_Widget *, void *);
|
|
xtc_result set_control_map(unsigned int channel, const unsigned int controllers[3]);
|
|
xtc_result add_plugin(const char *path, unsigned int index, size_t *id = nullptr);
|
|
xtc_result set_plugin_automation(size_t id, const xtc_plugin_point &point, bool remove = false);
|
|
xtc_result replace_plugin(size_t id, const char *path, unsigned int index);
|
|
xtc_result reset_plugin(size_t id, unsigned int port = UINT32_MAX);
|
|
xtc_result insert_plugin(const xtc_connection_info &wire, const char *path, unsigned int index, size_t *id = nullptr);
|
|
xtc_result set_plugin_control(size_t id, unsigned int port, float value);
|
|
/**
|
|
* @brief Constructs the window, its widgets, and the initial project.
|
|
*
|
|
* Creates an empty project and undo history, opens the audio backend, and
|
|
* schedules the periodic status timer. Throws std::runtime_error when the
|
|
* initial project or history cannot be created.
|
|
*
|
|
* @param prompt_unsaved Whether open, new, and close actions ask before
|
|
* discarding unsaved changes.
|
|
*/
|
|
explicit MainWindow(bool prompt_unsaved = true, const char *configuration = nullptr);
|
|
/**
|
|
* @brief Removes the status timer and releases backend and recording state.
|
|
*
|
|
* A backend that fails to close is intentionally retained with its recorder
|
|
* until process exit so active callbacks never observe freed state.
|
|
*/
|
|
~MainWindow() override;
|
|
/**
|
|
* @brief Deleted copy constructor; a window uniquely owns its project and backend.
|
|
*/
|
|
MainWindow(const MainWindow &) = delete;
|
|
/**
|
|
* @brief Deleted copy assignment; a window uniquely owns its project and backend.
|
|
*/
|
|
MainWindow &operator=(const MainWindow &) = delete;
|
|
using Fl_Double_Window::show;
|
|
/**
|
|
* @brief Handles FLTK events for the window.
|
|
*
|
|
* Space without Ctrl/Alt/Meta toggles the audio engine and is consumed.
|
|
*
|
|
* @param event FLTK event code, such as FL_SHORTCUT.
|
|
* @return 1 when Space was consumed; otherwise the Fl_Double_Window result.
|
|
*/
|
|
int handle(int event) override;
|
|
|
|
/**
|
|
* @brief Applies one undo or redo step from the project history.
|
|
*
|
|
* The selected snapshot is installed without resetting history and then
|
|
* accepted, leaving the window marked dirty.
|
|
*
|
|
* @param redo True to redo, false to undo.
|
|
* @return XTC_OK on success, XTC_ERR_INVALID_STATE while recording,
|
|
* XTC_ERR_NOT_FOUND when no step is available, or another error from
|
|
* checkout, install, or accept.
|
|
*/
|
|
xtc_result undo(bool redo = false);
|
|
|
|
/**
|
|
* @brief Returns the mixer tab widget owned by the window.
|
|
*
|
|
* @return Borrowed mixer widget, or nullptr before construction completes.
|
|
*/
|
|
MixerWidget *mixer() const
|
|
{
|
|
return mixer_;
|
|
}
|
|
|
|
/**
|
|
* @brief Shows the piano roll for the selected MIDI clip.
|
|
*
|
|
* The piano-roll window is created on first use and reused afterwards.
|
|
*
|
|
* @return XTC_OK on success, or XTC_ERR_INVALID_STATE when the selected clip
|
|
* does not exist or is not MIDI.
|
|
*/
|
|
xtc_result open_piano_roll();
|
|
|
|
/**
|
|
* @brief Returns the piano-roll editor widget.
|
|
*
|
|
* @return Borrowed widget, or nullptr until open_piano_roll() first succeeds.
|
|
*/
|
|
PianoRollWidget *piano_roll() const
|
|
{
|
|
return piano_;
|
|
}
|
|
|
|
/**
|
|
* @brief Imports a WAV file as an audio clip in a cloned project.
|
|
*
|
|
* Stops the engine first, creates an "Audio" track when none is selected,
|
|
* and places the clip at the sequencer cursor. The clone replaces the live
|
|
* project only after every step succeeds.
|
|
*
|
|
* @param path Path to the WAV file to import.
|
|
* @return XTC_OK on success, or an error from the engine stop, clone, import,
|
|
* or backend preparation.
|
|
*/
|
|
xtc_result import_audio(const char *path);
|
|
/**
|
|
* @brief Starts recording JACK input to a WAV file.
|
|
*
|
|
* Requires a connected backend and no active recording. The engine is
|
|
* stopped, the current position and selected track are remembered, and a
|
|
* stereo recorder at the engine sample rate is attached before starting.
|
|
* Failure leaves the window without a recorder.
|
|
*
|
|
* @param path Destination WAV path chosen by the user.
|
|
* @return XTC_OK when recording started, XTC_ERR_INVALID_STATE when
|
|
* disconnected or already recording, or another backend or recorder
|
|
* error.
|
|
*/
|
|
xtc_result record_audio(const char *path);
|
|
/**
|
|
* @brief Saves the current project to a path and updates the window title.
|
|
*
|
|
* On success the path is remembered and the unsaved marker is cleared.
|
|
*
|
|
* @param path Destination project path; nullptr is invalid.
|
|
* @return XTC_OK on success, XTC_ERR_INVALID_ARGUMENT for nullptr,
|
|
* XTC_ERR_INVALID_STATE while recording, or the save error.
|
|
*/
|
|
xtc_result save_project(const char *path);
|
|
/**
|
|
* @brief Loads a project from a path and makes it the current project.
|
|
*
|
|
* The file is loaded into a candidate project and installed only on success.
|
|
*
|
|
* @param path Source project path; nullptr is invalid.
|
|
* @return XTC_OK on success, XTC_ERR_INVALID_ARGUMENT for nullptr, or an
|
|
* error from loading or installing the project.
|
|
*/
|
|
xtc_result open_project(const char *path);
|
|
|
|
/** Creates a fresh untitled project; the File menu checks unsaved changes first.
|
|
* On failure the current document remains owned by the window. */
|
|
xtc_result new_project();
|
|
/** Requests a playback fade/stop; the timer completes deactivation after
|
|
* callback acknowledgement. Recording must use immediate Stop instead.
|
|
* Returns request acceptance or the backend failure. */
|
|
xtc_result pause_playback();
|
|
/** Stops playback and seeks to zero. Refuses during recording. A failed
|
|
* stop/seek is reported without moving the displayed cursor to zero. */
|
|
xtc_result return_to_start();
|
|
|
|
private:
|
|
friend class TrackInsertsPanel;
|
|
xtc_tap_tempo tap_state_{};
|
|
TrackInsertsPanel *track_inserts_=nullptr;
|
|
using MixSnapshot=std::unique_ptr<xtc_mix_snapshot,decltype(&xtc_mix_snapshot_destroy)>;
|
|
MixSnapshot mix_snapshots_[2]{{nullptr,xtc_mix_snapshot_destroy},{nullptr,xtc_mix_snapshot_destroy}};
|
|
struct EditorPanel {
|
|
MainWindow *owner=nullptr;unsigned int index=0;
|
|
Fl_Group *page=nullptr,*content=nullptr,*placeholder=nullptr;
|
|
std::unique_ptr<Fl_Double_Window> window;bool detached=false;
|
|
};
|
|
EditorPanel editors_[2];
|
|
Fl_Group *piano_page_=nullptr,*piano_content_=nullptr,*piano_placeholder_=nullptr;
|
|
bool piano_detached_=true;
|
|
std::unique_ptr<Fl_Double_Window> transport_window_, mixer_window_;
|
|
Fl_Group *transport_group_=nullptr, *mixer_page_=nullptr, *sidebar_=nullptr;
|
|
Fl_Group *mixer_placeholder_=nullptr;
|
|
struct TransportItem {Fl_Widget *widget;int x,y,w,h;};
|
|
std::vector<TransportItem> transport_items_;
|
|
bool layout_transport_busy_=false;
|
|
bool transport_detached_=false, mixer_detached_=false;
|
|
xtc_settings settings_{};
|
|
std::string configuration_;
|
|
bool configuration_valid_=true;
|
|
Fl_Check_Button *loop_button_=nullptr;
|
|
xtc_result configure_loop(const xtc_project *project,const xtc_settings &settings);
|
|
void apply_ui_preferences();
|
|
void collect_preferences();
|
|
void project_defaults(xtc_project *project);
|
|
double sample_rate() const;
|
|
void draw() override;
|
|
void refresh_workspace();
|
|
Fl_Choice *snap_ = nullptr, *piano_snap_ = nullptr;
|
|
Fl_Value_Slider *note_velocity_ = nullptr;
|
|
Fl_Widget *velocity_lane_ = nullptr;
|
|
Fl_Box *transport_position_ = nullptr;
|
|
Fl_Value_Input *tempo_display_ = nullptr;
|
|
Fl_Value_Input *inspector_gain_=nullptr,*inspector_pan_=nullptr;
|
|
Fl_Check_Button *inspector_mute_=nullptr,*inspector_solo_=nullptr,*follow_=nullptr;
|
|
Fl_Scroll *timeline_scroll_=nullptr;
|
|
Fl_Box *session_info_=nullptr;
|
|
uint64_t inspected_track_=UINT64_MAX;
|
|
static void inspector_callback(Fl_Widget *,void *);
|
|
void follow_playhead();
|
|
Fl_Box *selection_info_ = nullptr;
|
|
MixerWidget *mixer_ = nullptr;
|
|
Fl_Menu_Bar *menu_ = nullptr;
|
|
void update_history_controls();
|
|
std::unique_ptr<xtc_history, decltype(&xtc_history_destroy)> history_{nullptr, xtc_history_destroy};
|
|
/**
|
|
* @brief FLTK menu callback for the Undo and Redo menu items.
|
|
*
|
|
* The selected menu label starting with "Redo" chooses redo; all other
|
|
* labels undo. Failures other than XTC_ERR_NOT_FOUND are shown in the window.
|
|
*
|
|
* @param widget Fl_Menu_Bar whose selected item triggered the callback.
|
|
* @param context MainWindow * owning the menu and history.
|
|
*/
|
|
static void history_callback(Fl_Widget * widget, void * context);
|
|
std::unique_ptr<xtc_project, decltype(&xtc_project_destroy)> project_{nullptr, xtc_project_destroy};
|
|
std::unique_ptr<Fl_Double_Window> piano_window_;
|
|
PianoRollWidget *piano_ = nullptr;
|
|
/**
|
|
* @brief FLTK callback for the Piano roll menu item and button.
|
|
*
|
|
* Refuses to open the editor while recording and asks the user to select a
|
|
* MIDI clip when open_piano_roll() fails.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context MainWindow * owning the piano roll.
|
|
*/
|
|
static void piano_callback(Fl_Widget * widget, void *context);
|
|
/**
|
|
* @brief FLTK callback for the Panic menu item and button.
|
|
*
|
|
* When the backend is connected, sends a panic request that silences held
|
|
* instrument notes and reports failures.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context MainWindow * owning the backend.
|
|
*/
|
|
static void panic_callback(Fl_Widget * widget, void *context);
|
|
SequencerWidget *sequencer_ = nullptr;
|
|
xtc_recorder *recorder_ = nullptr;
|
|
std::string recording_path_;
|
|
uint64_t recording_tick_ = 0, recording_track_ = UINT64_MAX;
|
|
/**
|
|
* @brief Finalizes the active recording and adds the take to the project.
|
|
*
|
|
* Must run only after the engine has stopped, so no audio callback can
|
|
* reference the recorder ring. The recorder is detached, finished, and
|
|
* destroyed. A failed finalize or empty take is reported and not added. If
|
|
* the subsequent import fails, the saved WAV path is reported for recovery.
|
|
*/
|
|
void finish_recording();
|
|
/**
|
|
* @brief Hook called by arrangement widgets before mutating the project.
|
|
*
|
|
* Refuses edits while recording. When connected, stops the engine so the
|
|
* mutation cannot race the audio thread, then refreshes the status display.
|
|
*
|
|
* @param context MainWindow * passed as the widget owner context.
|
|
* @return XTC_OK when disconnected or the stop succeeded,
|
|
* XTC_ERR_INVALID_STATE while recording, or the backend stop error.
|
|
*/
|
|
static xtc_result before_arrangement_edit(void *context);
|
|
/**
|
|
* @brief FLTK callback for the audio import, record, and relink commands.
|
|
*
|
|
* The triggering widget supplies the menu label; the Record button uses the
|
|
* "Record WAV" default. A native file chooser selects the file, after which
|
|
* the selected clip is relinked, recording starts, or a WAV is imported.
|
|
* Failures are reported in the window.
|
|
*
|
|
* @param widget Triggering Fl_Menu_Bar or Fl_Button; menu labels select the
|
|
* action.
|
|
* @param context MainWindow * owning the project and sequencer.
|
|
*/
|
|
static void audio_file_callback(Fl_Widget * widget, void *context);
|
|
bool dirty_ = false, prompt_unsaved_ = true;
|
|
std::string path_;
|
|
/**
|
|
* @brief Asks whether unsaved changes may be discarded.
|
|
*
|
|
* @return True when the project is clean, prompting is disabled, or the user
|
|
* chose Discard; false when the user cancels.
|
|
*/
|
|
bool discard_changes();
|
|
/**
|
|
* @brief Records the current project in history and marks the window dirty.
|
|
*
|
|
* Dependent widgets are refreshed with the current project and graph, and
|
|
* the title gains the unsaved marker. A history failure is reported.
|
|
*/
|
|
void mark_dirty();
|
|
/**
|
|
* @brief Installs a candidate project as the active project.
|
|
*
|
|
* Rejected while recording. Optionally builds fresh undo history, stops and
|
|
* prepares the connected backend, or validates offline audio and MIDI plans
|
|
* when disconnected. On success the window takes ownership of candidate,
|
|
* rebinds widgets, resets the graph layout, clears the dirty flag, and shows
|
|
* any missing-asset warning. On failure ownership stays with the caller.
|
|
*
|
|
* @param candidate Project to install; must be non-null.
|
|
* @param reset_history True to discard existing undo/redo history and start
|
|
* from candidate.
|
|
* @return XTC_OK on success, XTC_ERR_INVALID_STATE while recording, or an
|
|
* error from history creation, the backend, or offline planning.
|
|
*/
|
|
xtc_result install_project(xtc_project *candidate, bool reset_history = true);
|
|
/**
|
|
* @brief Hook used by the sequencer to seek the audio engine.
|
|
*
|
|
* Does nothing when the backend is disconnected. Otherwise reads the engine
|
|
* sample rate, converts the tick position to samples, and seeks the backend.
|
|
*
|
|
* @param context MainWindow * passed as the sequencer owner context.
|
|
* @param tick Target timeline position in project ticks.
|
|
* @return XTC_OK when disconnected or the seek succeeded, or the status,
|
|
* conversion, or backend seek error.
|
|
*/
|
|
static xtc_result seek(void *context, uint64_t tick);
|
|
/**
|
|
* @brief FLTK menu callback for the File/New, Open, Save, and Save As items.
|
|
*
|
|
* Reads the action from the selected menu label, confirms discarding unsaved
|
|
* changes for New and Open, and uses a native file chooser unless Save can
|
|
* reuse the remembered path. Refuses file operations while recording and
|
|
* reports failures in the window.
|
|
*
|
|
* @param widget Triggering Fl_Menu_Bar whose selected label names the action.
|
|
* @param context MainWindow * owning the project and file path.
|
|
*/
|
|
static void control_map_callback(Fl_Widget *widget, void *context);
|
|
static void plugin_callback(Fl_Widget *widget, void *context);
|
|
xtc_result apply_plugin_spec(size_t id, const xtc_plugin_spec &spec, bool replace = false);
|
|
xtc_result install_plugin_graph(xtc_graph *graph);
|
|
static void file_callback(Fl_Widget * widget, void *context);
|
|
GraphWidget *graph_widget_ = nullptr;
|
|
Fl_Box *graph_state_ = nullptr;
|
|
xtc_backend *backend_ = nullptr;
|
|
std::string project_issue_;
|
|
bool ready_ = false;
|
|
bool running_ = false;
|
|
bool closing_ = false;
|
|
Fl_Button *record_ = nullptr;
|
|
Fl_Button *play_ = nullptr;
|
|
Fl_Button *stop_ = nullptr;
|
|
Fl_Button *pause_ = nullptr;
|
|
Fl_Button *home_ = nullptr;
|
|
Fl_Box *indicator_ = nullptr;
|
|
Fl_Box *status_ = nullptr;
|
|
Fl_Box *error_ = nullptr;
|
|
Fl_Tabs *tabs_ = nullptr;
|
|
|
|
/**
|
|
* @brief Edit handler passed to the modular graph widget.
|
|
*
|
|
* Applies the edit to a candidate graph, clones the project around it, and
|
|
* submits the new graph to the engine when connected. The live project is
|
|
* replaced only after every step succeeds.
|
|
*
|
|
* @param context MainWindow * passed as the graph widget owner context.
|
|
* @param edit Graph edit to apply.
|
|
* @param out_added_id Optional output receiving the new node ID when the edit
|
|
* adds a node; untouched otherwise or when nullptr.
|
|
* @return XTC_OK on success, XTC_ERR_INVALID_STATE while recording, or an
|
|
* error from the graph, project, or backend operation.
|
|
*/
|
|
static xtc_result edit_graph(void *context, const xtc_graph_edit &edit, size_t *out_added_id);
|
|
/**
|
|
* @brief Opens the JACK backend and submits the current graph.
|
|
*
|
|
* Uses the default backend configuration and leaves the engine stopped.
|
|
* Failure is reported and leaves the backend disconnected; a handle that
|
|
* opened but failed to accept the graph is retained for reconnect.
|
|
*/
|
|
void open_backend();
|
|
/**
|
|
* @brief Starts the audio engine with the current project.
|
|
*
|
|
* Does nothing when already running. Reports an error when disconnected.
|
|
* Otherwise prepares the project and starts the engine. Missing or
|
|
* unreadable audio is reported as a warning after a successful start.
|
|
*/
|
|
void start_engine();
|
|
/**
|
|
* @brief Requests a graceful playback stop, or immediately finalizes recording.
|
|
*
|
|
* Does nothing when disconnected. Failures are reported in the window.
|
|
*/
|
|
void stop_engine();
|
|
/**
|
|
* @brief Closes and reopens the JACK backend, leaving the engine stopped.
|
|
*
|
|
* Refuses to run while recording. If closing fails the existing handle is
|
|
* retained for a later retry and the failure is reported.
|
|
*/
|
|
void reconnect_engine();
|
|
/**
|
|
* @brief Polls the backend and updates labels, meters, and button states.
|
|
*
|
|
* When disconnected, shows offline text and disables transport controls.
|
|
* Otherwise updates the sequencer position, mixer peaks, status line, and
|
|
* error indicators from the latest engine status, then collects backend
|
|
* work.
|
|
*/
|
|
void refresh_status();
|
|
/**
|
|
* @brief Attempts to close the window after discarding unsaved changes.
|
|
*
|
|
* Refuses while recording. On success closes the backend, removes the status
|
|
* timer, hides the piano-roll window, and hides this window.
|
|
*
|
|
* @return True when the window closed; false when recording is active, the
|
|
* user cancels discarding, or the backend cannot close.
|
|
*/
|
|
bool close_window();
|
|
/**
|
|
* @brief Shows an operation failure and a context-sensitive hint.
|
|
*
|
|
* @param operation Human-readable operation name; names containing
|
|
* "Project" select a file and permission hint.
|
|
* @param result Failing result code whose name is included in the message.
|
|
*/
|
|
void report_error(const char *operation, xtc_result result);
|
|
/**
|
|
* @brief FLTK callback for the Play menu item and button.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context MainWindow * whose engine is started.
|
|
*/
|
|
static void play_callback(Fl_Widget * widget, void *context);
|
|
/**
|
|
* @brief FLTK callback for the Stop menu item and button.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context MainWindow * whose engine is stopped.
|
|
*/
|
|
static void stop_callback(Fl_Widget * widget, void *context);
|
|
/**
|
|
* @brief FLTK callback for the Reconnect menu item and button.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context MainWindow * whose backend is reopened.
|
|
*/
|
|
static void reconnect_callback(Fl_Widget * widget, void *context);
|
|
/**
|
|
* @brief FLTK callback for the window close box, File/Quit, and close events.
|
|
*
|
|
* @param widget Unused triggering widget or window.
|
|
* @param context MainWindow * whose close is requested; a refused close
|
|
* simply leaves the window open.
|
|
*/
|
|
static void close_callback(Fl_Widget * widget, void *context);
|
|
/**
|
|
* @brief FLTK menu callback that selects a tab page in the main window.
|
|
*
|
|
* @param widget Triggering menu item; window() must return the MainWindow.
|
|
* @param view Fl_Widget * tab page to make current, not the MainWindow.
|
|
*/
|
|
static void view_callback(Fl_Widget *widget, void *view);
|
|
/**
|
|
* @brief FLTK help callback that shows the application name and version.
|
|
*
|
|
* @param widget Unused triggering widget.
|
|
* @param context Unused callback context.
|
|
*/
|
|
static void about_callback(Fl_Widget * widget, void * context);
|
|
/**
|
|
* @brief FLTK timeout callback that refreshes status and supervises recording.
|
|
*
|
|
* While recording, drains the recorder and stops the engine if draining
|
|
* fails or the backend reports a lost server, sample-rate change, or
|
|
* processing error. Reschedules itself every 0.1 seconds until closing.
|
|
*
|
|
* @param context MainWindow * registered with Fl::add_timeout().
|
|
*/
|
|
static void timer_callback(void *context);
|
|
};
|
|
|
|
#endif
|