mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-10 23:46:20 +01:00
RecorderUI: Capture info and transport ctrls
This commit is contained in:
parent
7aa25e7b1d
commit
3f6be2f249
6 changed files with 341 additions and 5 deletions
244
gtk2_ardour/rec_info_box.cc
Normal file
244
gtk2_ardour/rec_info_box.cc
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef WAF_BUILD
|
||||
#include "gtk2ardour-config.h"
|
||||
#endif
|
||||
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/session_route.h"
|
||||
#include "ardour/track.h"
|
||||
|
||||
#include "gtkmm2ext/utils.h"
|
||||
#include "temporal/time.h"
|
||||
|
||||
#include "audio_clock.h"
|
||||
#include "gui_thread.h"
|
||||
#include "rec_info_box.h"
|
||||
#include "timers.h"
|
||||
#include "ui_config.h"
|
||||
|
||||
#include "pbd/i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
RecInfoBox::RecInfoBox ()
|
||||
{
|
||||
set_name (X_("RecInfoBox"));
|
||||
_layout_label = Pango::Layout::create (get_pango_context ());
|
||||
_layout_value = Pango::Layout::create (get_pango_context ());
|
||||
|
||||
UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &RecInfoBox::dpi_reset));
|
||||
dpi_reset ();
|
||||
}
|
||||
|
||||
RecInfoBox::~RecInfoBox ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::dpi_reset ()
|
||||
{
|
||||
_layout_label->set_font_description (UIConfiguration::instance ().get_NormalFont ());
|
||||
_layout_value->set_font_description (UIConfiguration::instance ().get_LargeMonospaceFont ());
|
||||
|
||||
int wl, hl, wv, hv;
|
||||
|
||||
_layout_label->set_text (_("Last Capture Duration:"));
|
||||
_layout_label->get_pixel_size (wl, hl);
|
||||
|
||||
_layout_value->set_text ("00:00:00:00");
|
||||
_layout_value->get_pixel_size (wv, hv);
|
||||
|
||||
_width = 8 + std::max (wl, wv);
|
||||
_height = 4 + 3 * (hl + hv + 8);
|
||||
|
||||
queue_resize ();
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::on_size_request (Gtk::Requisition* r)
|
||||
{
|
||||
r->width = _width;
|
||||
r->height = std::max (150, _height);
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::on_size_allocate (Gtk::Allocation& a)
|
||||
{
|
||||
CairoWidget::on_size_allocate (a);
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::set_session (Session* s)
|
||||
{
|
||||
SessionHandlePtr::set_session (s);
|
||||
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
_session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RecInfoBox::rec_state_changed, this), gui_context());
|
||||
_session->UpdateRouteRecordState.connect (_session_connections, invalidator (*this), boost::bind (&RecInfoBox::update, this), gui_context());
|
||||
update ();
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::rec_state_changed ()
|
||||
{
|
||||
if (_session && _session->actively_recording ()) {
|
||||
if (!_rectime_connection.connected ()) {
|
||||
_rectime_connection = Timers::rapid_connect (sigc::mem_fun (*this, &RecInfoBox::update));
|
||||
}
|
||||
} else {
|
||||
_rectime_connection.disconnect ();
|
||||
}
|
||||
update ();
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::update ()
|
||||
{
|
||||
set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::count_recenabled_streams (Route& route)
|
||||
{
|
||||
Track* track = dynamic_cast<Track*>(&route);
|
||||
if (track && track->rec_enable_control()->get_value()) {
|
||||
_rec_enabled_streams += track->n_inputs().n_total();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecInfoBox::render (Cairo::RefPtr<Cairo::Context> const& cr, cairo_rectangle_t* r)
|
||||
{
|
||||
int ww = get_width ();
|
||||
int hh = get_height ();
|
||||
|
||||
cr->rectangle (r->x, r->y, r->width, r->height);
|
||||
cr->clip ();
|
||||
cr->set_operator (Cairo::OPERATOR_OVER);
|
||||
|
||||
bool recording;
|
||||
if (_session && _session->actively_recording ()) {
|
||||
Gtkmm2ext::set_source_rgb_a (cr, UIConfiguration::instance ().color ("alert:red"), .7);
|
||||
recording = true;
|
||||
} else {
|
||||
Gtkmm2ext::set_source_rgb_a (cr, UIConfiguration::instance ().color ("widget:bg"), .7);
|
||||
recording = false;
|
||||
}
|
||||
|
||||
Gtkmm2ext::rounded_rectangle (cr, 1 , 1, ww - 2, hh - 2, /*_height / 4.0 */ 4);
|
||||
cr->fill ();
|
||||
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gtkmm2ext::set_source_rgba (cr, UIConfiguration::instance ().color ("neutral:foreground"));
|
||||
|
||||
unsigned int xruns = _session->capture_xruns ();
|
||||
samplecnt_t capture_duration = _session->capture_duration ();
|
||||
samplecnt_t sample_rate = _session->nominal_sample_rate ();
|
||||
|
||||
/* TODO: cache, calling this at rapid timer intervals when recording is not great */
|
||||
boost::optional<samplecnt_t> opt_samples = _session->available_capture_duration ();
|
||||
|
||||
int top = 2;
|
||||
int w, h;
|
||||
|
||||
if (recording || capture_duration == 0) {
|
||||
_layout_label->set_text (_("Capture Duration:"));
|
||||
} else {
|
||||
_layout_label->set_text (_("Last Capture Duration:"));
|
||||
}
|
||||
_layout_label->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_label->show_in_cairo_context (cr);
|
||||
top += h + 2;
|
||||
|
||||
if (capture_duration > 0) {
|
||||
char buf[32];
|
||||
AudioClock::print_minsec (capture_duration, buf, sizeof (buf), sample_rate, 1);
|
||||
_layout_value->set_text (std::string(buf).substr(1));
|
||||
} else {
|
||||
_layout_value->set_text ("--:--:--:-");
|
||||
}
|
||||
_layout_value->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_value->show_in_cairo_context (cr);
|
||||
top += h + 6;
|
||||
|
||||
_layout_label->set_text (_("Capture x-runs:"));
|
||||
_layout_label->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_label->show_in_cairo_context (cr);
|
||||
top += h + 2;
|
||||
|
||||
_layout_value->set_text (string_compose ("%1", xruns));
|
||||
_layout_value->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_value->show_in_cairo_context (cr);
|
||||
top += h + 6;
|
||||
|
||||
/* disk space */
|
||||
_layout_label->set_text (_("Available record time:"));
|
||||
_layout_label->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_label->show_in_cairo_context (cr);
|
||||
top += h + 2;
|
||||
|
||||
if (!opt_samples) {
|
||||
/* Available space is unknown */
|
||||
_layout_value->set_text (_("Unknown"));
|
||||
} else if (opt_samples.value_or (0) == max_samplecnt) {
|
||||
_layout_value->set_text (_(">24h"));
|
||||
} else {
|
||||
_rec_enabled_streams = 0;
|
||||
_session->foreach_route (this, &RecInfoBox::count_recenabled_streams, false);
|
||||
|
||||
samplecnt_t samples = opt_samples.value_or (0);
|
||||
|
||||
if (_rec_enabled_streams > 0) {
|
||||
samples /= _rec_enabled_streams;
|
||||
}
|
||||
|
||||
float remain_sec = samples / (float)sample_rate;
|
||||
char buf[32];
|
||||
|
||||
if (remain_sec > 86400) {
|
||||
_layout_value->set_text (_(">24h"));
|
||||
} else if (remain_sec > 32400 /* 9 hours */) {
|
||||
snprintf (buf, sizeof (buf), "%.0f", remain_sec / 3600.f);
|
||||
_layout_value->set_text (std::string (buf) + S_("hours|h"));
|
||||
} else if (remain_sec > 5940 /* 99 mins */) {
|
||||
snprintf (buf, sizeof (buf), "%.1f", remain_sec / 3600.f);
|
||||
_layout_value->set_text (std::string (buf) + S_("hours|h"));
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%.0f", remain_sec / 60.f);
|
||||
_layout_value->set_text (std::string (buf) + S_("minutes|m"));
|
||||
}
|
||||
}
|
||||
|
||||
_layout_value->get_pixel_size (w, h);
|
||||
cr->move_to (.5 * (ww - w), top);
|
||||
_layout_value->show_in_cairo_context (cr);
|
||||
top += h + 6;
|
||||
}
|
||||
58
gtk2_ardour/rec_info_box.h
Normal file
58
gtk2_ardour/rec_info_box.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _rec_info_box_h_
|
||||
#define _rec_info_box_h_
|
||||
|
||||
#include "ardour/session_handle.h"
|
||||
|
||||
#include "gtkmm2ext/cairo_widget.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class Route;
|
||||
}
|
||||
|
||||
class RecInfoBox : public CairoWidget, public ARDOUR::SessionHandlePtr
|
||||
{
|
||||
public:
|
||||
RecInfoBox ();
|
||||
~RecInfoBox ();
|
||||
|
||||
void set_session (ARDOUR::Session*);
|
||||
|
||||
protected:
|
||||
void render (Cairo::RefPtr<Cairo::Context> const&, cairo_rectangle_t*);
|
||||
void on_size_request (Gtk::Requisition*);
|
||||
void on_size_allocate (Gtk::Allocation&);
|
||||
|
||||
private:
|
||||
void dpi_reset ();
|
||||
void update ();
|
||||
void rec_state_changed ();
|
||||
void count_recenabled_streams (ARDOUR::Route&);
|
||||
|
||||
Glib::RefPtr<Pango::Layout> _layout_label;
|
||||
Glib::RefPtr<Pango::Layout> _layout_value;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
uint32_t _rec_enabled_streams;
|
||||
sigc::connection _rectime_connection;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -84,6 +84,12 @@ RecorderUI::RecorderUI ()
|
|||
load_bindings ();
|
||||
register_actions ();
|
||||
|
||||
_transport_ctrl.setup (ARDOUR_UI::instance ());
|
||||
_transport_ctrl.map_actions ();
|
||||
_transport_ctrl.set_no_show_all ();
|
||||
|
||||
signal_tabbed_changed.connect (sigc::mem_fun (*this, &RecorderUI::tabbed_changed));
|
||||
|
||||
_meter_area.set_spacing (0);
|
||||
_meter_area.pack_start (_meter_table, true, true);
|
||||
_meter_area.signal_size_request().connect (sigc::mem_fun (*this, &RecorderUI::meter_area_size_request));
|
||||
|
|
@ -99,25 +105,30 @@ RecorderUI::RecorderUI ()
|
|||
_rec_area.pack_end (_scroller_base, true, true);
|
||||
_rec_area.pack_end (_ruler_sep, false, false, 1);
|
||||
|
||||
/* HBox groups | tracks */
|
||||
/* HBox [ groups | tracks] */
|
||||
_rec_group_tabs = new RecorderGroupTabs (this);
|
||||
_rec_groups.pack_start (*_rec_group_tabs, false, false);
|
||||
_rec_groups.pack_start (_rec_area, true, true);
|
||||
|
||||
/* vertical scroll, all tracks */
|
||||
/* Vertical scroll, all tracks */
|
||||
_rec_scroller.add (_rec_groups);
|
||||
_rec_scroller.set_shadow_type(SHADOW_NONE);
|
||||
_rec_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
|
||||
|
||||
/* HBox, ruler on top */
|
||||
/* HBox, ruler on top [ space above headers | time-ruler ] */
|
||||
_ruler_box.pack_start (_space, false, false);
|
||||
_ruler_box.pack_start (_ruler, true, true);
|
||||
|
||||
/* VBox, toplevel of upper pane */
|
||||
/* VBox, ruler + scroll-area for tracks */
|
||||
_rec_container.pack_start (_ruler_box, false, false);
|
||||
_rec_container.pack_start (_rec_scroller, true, true);
|
||||
|
||||
_pane.add (_rec_container);
|
||||
/* HBox, toplevel of upper pane [Info | recarea ] */
|
||||
_rec_container.pack_start (_ruler_box, false, false);
|
||||
_rec_top.pack_start (_rec_info_box, false, false, 4);
|
||||
_rec_top.pack_start (_rec_container, true, true);
|
||||
|
||||
_pane.add (_rec_top);
|
||||
_pane.add (_meter_scroller);
|
||||
|
||||
_content.pack_start (_toolbar_sep, false, false, 1);
|
||||
|
|
@ -154,6 +165,7 @@ RecorderUI::RecorderUI ()
|
|||
_toolbar.pack_start (_btn_peak_reset, false, false);
|
||||
_toolbar.pack_start (*manage (new ArdourVSpacer), false, false);
|
||||
_toolbar.pack_start (_btn_rec_forget, false, false);
|
||||
_toolbar.pack_start (_transport_ctrl, false, false);
|
||||
|
||||
set_tooltip (_btn_rec_all, _("Record enable all tracks"));
|
||||
set_tooltip (_btn_rec_none, _("Disable recording of all tracks"));
|
||||
|
|
@ -172,6 +184,7 @@ RecorderUI::RecorderUI ()
|
|||
_rec_groups.show ();
|
||||
_rec_group_tabs->show ();
|
||||
_rec_container.show ();
|
||||
_rec_top.show ();
|
||||
_meter_table.show ();
|
||||
_meter_area.show ();
|
||||
_meter_scroller.show ();
|
||||
|
|
@ -235,6 +248,16 @@ RecorderUI::use_own_window (bool and_fill_it)
|
|||
return win;
|
||||
}
|
||||
|
||||
void
|
||||
RecorderUI::tabbed_changed (bool tabbed)
|
||||
{
|
||||
if (tabbed) {
|
||||
_transport_ctrl.hide ();
|
||||
} else {
|
||||
_transport_ctrl.show ();
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
RecorderUI::get_state ()
|
||||
{
|
||||
|
|
@ -268,6 +291,8 @@ RecorderUI::set_session (Session* s)
|
|||
SessionHandlePtr::set_session (s);
|
||||
|
||||
_ruler.set_session (s);
|
||||
_rec_info_box.set_session (s);
|
||||
_transport_ctrl.set_session (s);
|
||||
_rec_group_tabs->set_session (s);
|
||||
|
||||
update_sensitivity ();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@
|
|||
#include "widgets/tabbable.h"
|
||||
|
||||
#include "input_port_monitor.h"
|
||||
#include "rec_info_box.h"
|
||||
#include "transport_control_ui.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class SoloMuteRelease;
|
||||
|
|
@ -90,6 +92,7 @@ private:
|
|||
void remove_route (TrackRecordAxis*);
|
||||
void update_rec_table_layout ();
|
||||
void update_spacer_width (Gtk::Allocation&, TrackRecordAxis*);
|
||||
void tabbed_changed (bool);
|
||||
|
||||
void set_connections (std::string const&);
|
||||
void port_connected_or_disconnected (std::string, std::string);
|
||||
|
|
@ -116,6 +119,7 @@ private:
|
|||
Gtkmm2ext::Bindings* bindings;
|
||||
Gtk::VBox _content;
|
||||
Gtk::HBox _toolbar;
|
||||
Gtk::HBox _rec_top;
|
||||
ArdourWidgets::VPane _pane;
|
||||
Gtk::ScrolledWindow _rec_scroller;
|
||||
Gtk::VBox _rec_container;
|
||||
|
|
@ -132,6 +136,8 @@ private:
|
|||
ArdourWidgets::ArdourButton _btn_rec_forget;
|
||||
ArdourWidgets::ArdourButton _btn_new_take;
|
||||
ArdourWidgets::ArdourButton _btn_peak_reset;
|
||||
RecInfoBox _rec_info_box;
|
||||
TransportControlUI _transport_ctrl;
|
||||
|
||||
int _meter_box_width;
|
||||
int _meter_area_cols;
|
||||
|
|
|
|||
|
|
@ -160,6 +160,8 @@ TransportControlUI::setup (TransportControlProvider* ui)
|
|||
|
||||
stop_button.set_active (true);
|
||||
|
||||
show_all ();
|
||||
|
||||
Timers::blink_connect (sigc::mem_fun (*this, &TransportControlUI::blink_rec_enable));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ gtk2_ardour_sources = [
|
|||
'public_editor.cc',
|
||||
'quantize_dialog.cc',
|
||||
'rc_option_editor.cc',
|
||||
'rec_info_box.cc',
|
||||
'recorder_group_tabs.cc',
|
||||
'recorder_ui.cc',
|
||||
'region_editor.cc',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue