post-export scaleable layout.
authorRobin Gareus <robin@gareus.org>
Thu, 11 Feb 2016 13:07:32 +0000 (14:07 +0100)
committerRobin Gareus <robin@gareus.org>
Thu, 11 Feb 2016 13:14:01 +0000 (14:14 +0100)
gtk2_ardour/export_report.cc

index 0e445f40bea4dcc83dd3a8383e102158e5f1d3d1..e4aac1e0fbd610af6d4ef76eb9957fbb1f0af36b 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <algorithm>
+
 #include <pangomm/layout.h>
 #include <gtkmm/label.h>
 #include <gtkmm/table.h>
@@ -27,6 +29,7 @@
 
 #include "ardour/audiofilesource.h"
 #include "ardour/session.h"
+#include "ardour/ardour/dB.h"
 
 #include "audio_clock.h"
 #include "ui_config.h"
@@ -41,6 +44,8 @@ ExportReport::ExportReport (Session* _session, StatusPtr s)
        : ArdourDialog (_("Export Report/Analysis"))
        , status (s)
 {
+       set_resizable (false);
+       pages.set_scrollable ();
 
        AnalysisResults & ar = status->result_map;
 
@@ -51,41 +56,64 @@ ExportReport::ExportReport (Session* _session, StatusPtr s)
        for (AnalysisResults::iterator i = ar.begin (); i != ar.end (); ++i) {
                Label *l;
                VBox *vb = manage (new VBox ());
-               Table *t = manage (new Table (4,4));
-               t->set_spacings (6);
-               vb->set_spacing (6);
-               vb->pack_start (*t);
+               Table *t = manage (new Table (4, 4));
+               t->set_spacings (4);
+               vb->set_spacing (4);
+               vb->pack_start (*t, false, false, 2);
 
                std::string path = i->first;
+               ExportAnalysisPtr p = i->second;
 
                l = manage (new Label (_("File:"), ALIGN_END));
                t->attach (*l, 0, 1, 0, 1);
-               l = manage (new Label (path, ALIGN_START));
-               t->attach (*l, 1, 4, 0, 1);
+               l = manage (new Label ());
+               l->set_ellipsize (Pango::ELLIPSIZE_START);
+               l->set_width_chars (64);
+               l->set_max_width_chars (64);
+               l->set_text (path);
+               l->set_alignment (ALIGN_START, ALIGN_CENTER);
+               t->attach (*l, 1, 4, 0, 1, FILL, SHRINK);
 
                SoundFileInfo info;
                std::string errmsg;
 
+               framecnt_t file_length = 0;
+               framecnt_t sample_rate = 0;
+               framecnt_t start_off = 0;
+
                if (AudioFileSource::get_soundfile_info (path, info, errmsg)) {
                        AudioClock * clock;
 
-                       framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
+                       file_length = info.length;
+                       sample_rate = info.samplerate;
+                       start_off = info.timecode;
+
+                       /* File Info Table */
+
+                       framecnt_t const nfr = _session ? _session->nominal_frame_rate () : 25;
                        double src_coef = (double) nfr / info.samplerate;
 
-                       l = manage (new Label (_("Channels:"), ALIGN_END));
+                       l = manage (new Label (_("Format:"), ALIGN_END));
                        t->attach (*l, 0, 1, 1, 2);
-                       l = manage (new Label (string_compose ("%1", info.channels)));
-                       t->attach (*l, 1, 2, 1, 2);
+                       std::string fmt = info.format_name;
+                       std::replace (fmt.begin (), fmt.end (), '\n', ' ');
+                       l = manage (new Label ());
+                       l->set_ellipsize (Pango::ELLIPSIZE_START);
+                       l->set_width_chars (64);
+                       l->set_max_width_chars (64);
+                       l->set_text (fmt);
+                       l->set_alignment (ALIGN_START, ALIGN_CENTER);
+                       t->attach (*l, 1, 4, 1, 2, FILL, SHRINK);
 
-                       l = manage (new Label (_("Format:"), ALIGN_END));
-                       t->attach (*l, 2, 3, 1, 3);
-                       l = manage (new Label (info.format_name));
-                       t->attach (*l, 3, 4, 1, 3);
+                       l = manage (new Label (_("Channels:"), ALIGN_END));
+                       t->attach (*l, 0, 1, 2, 3);
+                       l = manage (new Label (string_compose ("%1", info.channels)));
+                       t->attach (*l, 1, 2, 2, 3);
 
                        l = manage (new Label (_("Sample rate:"), ALIGN_END));
-                       t->attach (*l, 0, 1, 2, 3);
+                       t->attach (*l, 2, 3, 2, 3);
                        l = manage (new Label (string_compose (_("%1 Hz"), info.samplerate)));
-                       t->attach (*l, 1, 2, 2, 3);
+                       t->attach (*l, 3, 4, 2, 3);
 
                        l = manage (new Label (_("Duration:"), ALIGN_END));
                        t->attach (*l, 0, 1, 3, 4);
@@ -109,137 +137,197 @@ ExportReport::ExportReport (Session* _session, StatusPtr s)
                        t->attach (*l, 1, 4, 1, 2);
                }
 
-               ExportAnalysisPtr p = i->second;
+               int w, h;
+               Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (get_pango_context ());
 
-               {
-                       /* EBU R128 loudness numerics and histogram */
-                       int w, h;
-                       Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (get_pango_context ());
-                       Cairo::RefPtr<Cairo::ImageSurface> nums = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, 256, 128);
-                       Cairo::RefPtr<Cairo::ImageSurface> hist = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, 540, 128);
+               // calc geometry of numerics
+               const float dbfs = accurate_coefficient_to_dB (p->peak);
+               const float dbtp = accurate_coefficient_to_dB (p->truepeak);
+
+#define TXTSIZE(LINE, TXT, FONT) {                                     \
+  layout->set_font_description (UIConfiguration::instance ().FONT ()); \
+  layout->set_text (TXT);                                              \
+  layout->get_pixel_size (w, h);                                       \
+  if (w > mnw) { mnw = w; }                                            \
+  if (h > lin[LINE]) { lin[LINE] = h; }                                \
+}
+
+#define TXTWIDTH(TXT, FONT) {                                          \
+  layout->set_font_description (UIConfiguration::instance ().FONT ()); \
+  layout->set_text (TXT);                                              \
+  layout->get_pixel_size (w, h);                                       \
+  if (w > mml) { mml = w; }                                            \
+}
+
+               int mnw = 0; // max numeric width
+               int lin[4] = { 0, 0, 0, 0 }; // max line height
+
+               TXTSIZE(0, _("Peak:"), get_SmallFont);
+               TXTSIZE(1, string_compose (_("%1 dBFS"), std::setprecision (1), std::fixed, dbfs), get_LargeFont);
+               TXTSIZE(2, _("True Peak:"), get_SmallFont);
+               TXTSIZE(3, string_compose (_("%1 dBTP"), std::setprecision (1), std::fixed, dbtp), get_LargeFont);
+
+               TXTSIZE(0, _("Integrated Loudness:"), get_SmallFont);
+               TXTSIZE(1, string_compose (_("%1 LUFS"), std::setprecision (1), std::fixed, p->loudness), get_LargeFont);
+               TXTSIZE(2, _("Loudness Range:"), get_SmallFont);
+               TXTSIZE(3, string_compose (_("%1 LU"), std::setprecision (1), std::fixed, p->loudness_range), get_LargeFont);
 
+               mnw += 8;
+               const int ht = lin[0] * 1.25 + lin[1] * 1.25 + lin[2] * 1.25 + lin[3] + 8;
+               const int hh = std::max (100, ht);
+               int m_l =  2 * mnw + /*hist-width*/ 540 + /*box spacing*/ 8 - /*peak-width*/ 800; // margin left
+
+               int mml = 0; // min margin left -- ensure left margin is wide enough
+               TXTWIDTH (_("Time"), get_SmallFont);
+               TXTWIDTH (_("100"), get_SmallMonospaceFont);
+               m_l = (std::max (m_l, mml + 8) + 3) & ~3;
+
+               mnw = (m_l - /*hist-width*/ 540 - /*box spacing*/ 8 + /*peak-width*/ 800) / 2;
+               const int nw2 = mnw / 2; // nums, horizontal center
+
+               int y0[4];
+               y0[0] = (hh - ht) * .5 + lin[0] * .25;
+               y0[1] = y0[0] + lin[0] * 1.25;
+               y0[2] = y0[1] + lin[1] * 1.25;
+               y0[3] = y0[2] + lin[2] * 1.25;
+
+
+               { /* peak, loudness and R128 histogram */
+                       Cairo::RefPtr<Cairo::ImageSurface> nums = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, mnw, hh);
+                       Cairo::RefPtr<Cairo::ImageSurface> ebur = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, mnw, hh);
+                       Cairo::RefPtr<Cairo::ImageSurface> hist = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, 540, hh);
+
+                       /* peak and true-peak numerics */
                        Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (nums);
-                       cr->rectangle (0, 0, 256, 128);
                        cr->set_source_rgba (0, 0, 0, 1.0);
-                       cr->fill ();
+                       cr->paint ();
 
                        layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
                        layout->set_alignment (Pango::ALIGN_LEFT);
-                       layout->set_text (_("Ebu R128"));
+                       layout->set_text (_("Peak:"));
                        layout->get_pixel_size (w, h);
+                       cr->move_to (rint (nw2 - w * .5), y0[0]);
+                       cr->set_source_rgba (.7, .7, .7, 1.0);
+                       layout->show_in_cairo_context (cr);
 
-                       cr->save ();
-                       cr->set_source_rgba (.5, .5, .5, 1.0);
-                       cr->move_to (6, rint (64 + w * .5));
-                       cr->rotate (M_PI / -2.0);
+                       layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
+                       layout->set_text (string_compose (_("%1 dBFS"), std::setprecision (1), std::fixed,
+                                               accurate_coefficient_to_dB (p->peak)));
+                       layout->get_pixel_size (w, h);
+                       cr->move_to (rint (nw2 - w * .5), y0[1]);
+                       if (p->peak > .944) { cr->set_source_rgba (1.0, .5, .5, 1.0); }
                        layout->show_in_cairo_context (cr);
-                       cr->restore ();
+
+                       if (p->have_dbtp) {
+                               layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
+                               layout->set_text (_("True Peak:"));
+                               layout->get_pixel_size (w, h);
+                               cr->move_to (rint (nw2 - w * .5), y0[2]);
+                               cr->set_source_rgba (.7, .7, .7, 1.0);
+                               layout->show_in_cairo_context (cr);
+
+                               layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
+                               layout->set_text (string_compose (_("%1 dBTP"), std::setprecision (1), std::fixed,
+                                               accurate_coefficient_to_dB (p->truepeak)));
+                               layout->get_pixel_size (w, h);
+                               cr->move_to (rint (nw2 - w * .5), y0[3]);
+                               if (p->truepeak > .944) { cr->set_source_rgba (1.0, .5, .5, 1.0); }
+                               layout->show_in_cairo_context (cr);
+                       }
+
+                       nums->flush ();
+
+                       /* EBU R128 numerics */
+                       cr = Cairo::Context::create (ebur);
+                       cr->set_source_rgba (0, 0, 0, 1.0);
+                       cr->paint ();
 
                        cr->set_source_rgba (.7, .7, .7, 1.0);
 
                        if (!i->second->have_loudness) {
                                layout->set_alignment (Pango::ALIGN_CENTER);
                                layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
-                               layout->set_text (string_compose (_("not\navailable"), std::setprecision (1), std::fixed,  p->loudness));
+                               layout->set_text (_("not\navailable"));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), rint (64 - h * .5));
+                               cr->move_to (rint (nw2 - w * .5), rint (hh - h * .5));
                                layout->show_in_cairo_context (cr);
                        }
                        else if (p->loudness == -200 && p->loudness_range == 0) {
                                layout->set_alignment (Pango::ALIGN_CENTER);
                                layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
-                               layout->set_text (string_compose (_("not\navailable"), std::setprecision (1), std::fixed,  p->loudness));
+                               layout->set_text (_("not\navailable"));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), rint (64 - h * .6));
+                               cr->move_to (rint (nw2 - w * .5), rint (hh - h * .6));
                                layout->show_in_cairo_context (cr);
-                               int y0 = h * .5;
+                               int yy = h * .5;
 
                                layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
                                layout->set_text (_("(too short integration time)"));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), rint (64 + y0));
+                               cr->move_to (rint (nw2 - w * .5), rint (hh + yy));
                                layout->show_in_cairo_context (cr);
 
                        } else {
-                               // calc height
-                               int ht = 0;
-                               layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
-                               layout->set_text (string_compose (_("Integrated Loudness:"), std::setprecision (1), std::fixed,  p->loudness));
-                               layout->get_pixel_size (w, h);
-                               ht += h * 1.25;
-                               layout->set_text (string_compose (_("Loudness Range:"), std::setprecision (1), std::fixed,  p->loudness));
-                               layout->get_pixel_size (w, h);
-                               ht += h * 1.25;
-                               layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
-                               layout->set_text (string_compose (_("%1%2%3 LUFS"), std::setprecision (1), std::fixed,  p->loudness));
-                               layout->get_pixel_size (w, h);
-                               ht += h * 1.5;
-                               layout->set_text (string_compose (_("%1%2%3 LU"), std::setprecision (1), std::fixed, p->loudness_range));
-                               layout->get_pixel_size (w, h);
-                               ht += h;
-
-                               int y0 = (128 - ht) * .5;
-
                                layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
                                layout->set_alignment (Pango::ALIGN_LEFT);
-                               layout->set_text (string_compose (_("Integrated Loudness:"), std::setprecision (1), std::fixed,  p->loudness));
+                               layout->set_text (_("Integrated Loudness:"));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), y0);
+                               cr->move_to (rint (nw2 - w * .5), y0[0]);
                                layout->show_in_cairo_context (cr);
-                               y0 += h * 1.25;
 
                                layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
-                               layout->set_text (string_compose (_("%1%2%3 LUFS"), std::setprecision (1), std::fixed,  p->loudness));
+                               layout->set_text (string_compose (_("%1 LUFS"), std::setprecision (1), std::fixed,  p->loudness));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), y0);
+                               cr->move_to (rint (nw2 - w * .5), y0[1]);
                                layout->show_in_cairo_context (cr);
-                               y0 += h * 1.5;
 
                                layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
-                               layout->set_text (string_compose (_("Loudness Range:"), std::setprecision (1), std::fixed,  p->loudness));
+                               layout->set_text (_("Loudness Range:"));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), y0);
+                               cr->move_to (rint (nw2 - w * .5), y0[2]);
                                layout->show_in_cairo_context (cr);
-                               y0 += h * 1.25;
 
                                layout->set_font_description (UIConfiguration::instance ().get_LargeFont ());
-                               layout->set_text (string_compose (_("%1%2%3 LU"), std::setprecision (1), std::fixed, p->loudness_range));
+                               layout->set_text (string_compose (_("%1 LU"), std::setprecision (1), std::fixed, p->loudness_range));
                                layout->get_pixel_size (w, h);
-                               cr->move_to (rint (128 - w * .5), y0);
+                               cr->move_to (rint (nw2 - w * .5), y0[3]);
                                layout->show_in_cairo_context (cr);
                        }
-                       nums->flush ();
+                       ebur->flush ();
 
                        /* draw loudness histogram */
                        cr = Cairo::Context::create (hist);
-                       cr->rectangle (0, 0, 540, 128);
                        cr->set_source_rgba (0, 0, 0, 1.0);
-                       cr->fill ();
+                       cr->paint ();
 
                        cr->set_source_rgba (.7, .7, .7, 1.0);
                        cr->set_line_width (1.0);
 
                        if (p->loudness_hist_max > 0 && i->second->have_loudness) {
                                for (size_t x = 0 ; x < 510; ++x) {
-                                       cr->move_to (x - .5, 128.0);
-                                       cr->line_to (x - .5, 128.0 - 128.0 * p->loudness_hist[x] / (float) p->loudness_hist_max);
+                                       cr->move_to (x - .5, hh);
+                                       cr->line_to (x - .5, (float) hh * (1.0 - p->loudness_hist[x] / (float) p->loudness_hist_max));
                                        cr->stroke ();
                                }
                        }
 
-                       layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
                        layout->set_alignment (Pango::ALIGN_CENTER);
 
+                       // Label
                        layout->set_text (_("LUFS\n(short)"));
                        layout->get_pixel_size (w, h);
-                       Gtkmm2ext::rounded_rectangle (cr, 5, 5, w + 2, h + 2, 4);
+                       Gtkmm2ext::rounded_rectangle (cr, 5, rint (.5 * (hh - w) - 1), h + 2, w + 2, 4);
                        cr->set_source_rgba (.1, .1, .1, 0.7);
                        cr->fill ();
-
-                       cr->move_to (6, 6);
+                       cr->save ();
+                       cr->move_to (6, rint (.5 * (hh + w)));
                        cr->set_source_rgba (.9, .9, .9, 1.0);
+                       cr->rotate (M_PI / -2.0);
                        layout->show_in_cairo_context (cr);
+                       cr->restore ();
 
+                       // x-Axis
                        layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
                        layout->set_alignment (Pango::ALIGN_LEFT);
                        for (int g = -53; g <= -8; g += 5) {
@@ -269,138 +357,207 @@ ExportReport::ExportReport (Session* _session, StatusPtr s)
                                cr->set_dash (dashes, 1.0);
                                cr->set_line_cap (Cairo::LINE_CAP_ROUND);
                                cr->move_to (rint ((g + 59.0) * 10.0) + .5, w + 8.0);
-                               cr->line_to (rint ((g + 59.0) * 10.0) + .5, 128.0);
+                               cr->line_to (rint ((g + 59.0) * 10.0) + .5, hh);
                                cr->stroke ();
                                cr->restore ();
                        }
 
-                       cr->set_operator (Cairo::OPERATOR_ADD);
-
-
                        hist->flush ();
+
                        CimgArea *nu = manage (new CimgArea (nums));
+                       CimgArea *eb = manage (new CimgArea (ebur));
                        CimgArea *hi = manage (new CimgArea (hist));
                        HBox *hb = manage (new HBox ());
                        hb->set_spacing (4);
-                       hb->pack_start (*nu);
-                       hb->pack_start (*hi);
-                       vb->pack_start (*hb);
+                       hb->pack_start (*nu, false, false);
+                       hb->pack_start (*hi, false, false);
+                       hb->pack_start (*eb, false, false);
+                       vb->pack_start (*hb, false, false);
                }
 
+#define XAXISLABEL(POS, TXT) {                            \
+  const float yy = rint (POS);                            \
+  layout->set_text (TXT);                                 \
+  layout->get_pixel_size (w, h);                          \
+  cr->move_to (m_l - 8 - w, rint ((POS) - h * .5));       \
+  cr->set_source_rgba (.9, .9, .9, 1.0);                  \
+  cr->set_operator (Cairo::OPERATOR_OVER);                \
+  layout->show_in_cairo_context (cr);                     \
+  cr->move_to (m_l - 4, yy - .5);                         \
+  cr->line_to (m_l + width, yy - .5);                     \
+  cr->set_source_rgba (.3, .3, .3, 1.0);                  \
+  cr->set_operator (Cairo::OPERATOR_ADD);                 \
+  cr->stroke ();                                          \
+}
+
                for (uint32_t c = 0; c < p->n_channels; ++c) {
                        /* draw waveform */
-                       // TODO re-use Canvas::WaveView::draw_image() somehow.
                        const size_t width = sizeof (p->peaks) / sizeof (ARDOUR::PeakData::PeakDatum) / 4;
-                       const float height_2 = p->n_channels == 2 ? 66.0 : 100.0;
-                       Cairo::RefPtr<Cairo::ImageSurface> wave = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, width, 2 * height_2);
+                       const float height_2 = std::min (100, 8 * lin[0] / (int) p->n_channels); // TODO refine
+
+                       Cairo::RefPtr<Cairo::ImageSurface> wave = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, m_l + width, 2 * height_2);
                        Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (wave);
-                       cr->rectangle (0, 0, width, 2 * height_2);
+                       cr->set_operator (Cairo::OPERATOR_SOURCE);
+                       cr->rectangle (0, 0, m_l, 2 * height_2);
+                       cr->set_source_rgba (0, 0, 0, 0);
+                       cr->fill ();
+                       cr->rectangle (m_l, 0, width, 2 * height_2);
                        cr->set_source_rgba (0, 0, 0, 1.0);
                        cr->fill ();
+                       cr->set_operator (Cairo::OPERATOR_OVER);
+
                        cr->set_source_rgba (.7, .7, .7, 1.0);
                        cr->set_line_width (1.0);
                        for (size_t x = 0 ; x < width; ++x) {
-                               cr->move_to (x - .5, height_2 - height_2 * p->peaks[c][x].max);
-                               cr->line_to (x - .5, height_2 - height_2 * p->peaks[c][x].min);
+                               cr->move_to (m_l + x - .5, height_2 - height_2 * p->peaks[c][x].max);
+                               cr->line_to (m_l + x - .5, height_2 - height_2 * p->peaks[c][x].min);
                        }
                        cr->stroke ();
 
                        // zero line
                        cr->set_source_rgba (.3, .3, .3, 0.7);
-                       cr->move_to (0, height_2 - .5);
-                       cr->line_to (width, height_2 - .5);
+                       cr->move_to (m_l + 0, height_2 - .5);
+                       cr->line_to (m_l + width, height_2 - .5);
                        cr->stroke ();
 
-                       cr->set_dash (dashes, 2.0);
-                       cr->set_line_cap (Cairo::LINE_CAP_ROUND);
-
-                       Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (get_pango_context ());
-                       layout->set_alignment (Pango::ALIGN_LEFT);
+                       // Unit
                        layout->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
-                       int w, h;
-
+                       layout->set_alignment (Pango::ALIGN_LEFT);
                        layout->set_text (_("dBFS"));
                        layout->get_pixel_size (w, h);
-                       Gtkmm2ext::rounded_rectangle (cr,
-                                       7, rint (height_2 - w * .5 - 1), h + 2, w + 2, 4);
-                       cr->set_source_rgba (.1, .1, .1, 0.7);
-                       cr->fill ();
-                       cr->move_to (8, rint (height_2 + w * .5));
+                       cr->move_to (rint (.5 * (m_l - h)), rint (height_2 + w * .5));
                        cr->set_source_rgba (.9, .9, .9, 1.0);
                        cr->save ();
                        cr->rotate (M_PI / -2.0);
                        layout->show_in_cairo_context (cr);
                        cr->restore ();
 
-                       layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
-#define PEAKANNOTATION(POS, TXT) {                            \
-                       const float yy = rint (POS);                            \
-                       layout->set_text (TXT);                                 \
-                       layout->get_pixel_size (w, h);                          \
-                       cr->set_operator (Cairo::OPERATOR_OVER);                \
-                       Gtkmm2ext::rounded_rectangle (cr,                       \
-                           5, rint ((POS) - h * .5 - 1), w + 2, h + 2, 4);     \
-                       cr->set_source_rgba (.1, .1, .1, 0.7);                  \
-                       cr->fill ();                                            \
-                       cr->move_to (6, rint ((POS) - h * .5));                 \
-                       cr->set_source_rgba (.9, .9, .9, 1.0);                  \
-                       layout->show_in_cairo_context (cr);                     \
-                       cr->move_to (8 + w, yy - .5);                           \
-                       cr->line_to (width, yy - .5);                           \
-                       cr->set_source_rgba (.3, .3, .3, 1.0);                  \
-                       cr->set_operator (Cairo::OPERATOR_ADD);                 \
-                       cr->stroke ();                                          \
-                       }
+                       // x-Axis
+                       cr->set_line_width (1.0);
+                       cr->set_dash (dashes, 2.0);
+                       cr->set_line_cap (Cairo::LINE_CAP_ROUND);
 
-                       PEAKANNOTATION (height_2 * 0.6452, _("-9"));
-                       PEAKANNOTATION (height_2 * 1.3548, _("-9"));
-                       PEAKANNOTATION (height_2 * 0.2921, _("-3"));
-                       PEAKANNOTATION (height_2 * 1.7079, _("-3"));
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
+                       XAXISLABEL (height_2 * 0.6452, _("-9"));
+                       XAXISLABEL (height_2 * 1.3548, _("-9"));
+                       XAXISLABEL (height_2 * 0.2921, _("-3"));
+                       XAXISLABEL (height_2 * 1.7079, _("-3"));
 
                        wave->flush ();
                        CimgArea *wv = manage (new CimgArea (wave));
                        vb->pack_start (*wv);
                }
 
+               if (file_length > 0 && sample_rate > 0)
+               {
+                       /* Time Axis  -- re-use waveform width */
+                       const size_t width = sizeof (p->peaks) / sizeof (ARDOUR::PeakData::PeakDatum) / 4;
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
+                       layout->set_text (_("00:00:00.000"));
+                       layout->get_pixel_size (w, h);
+                       int height = h * 1.75;
+                       Cairo::RefPtr<Cairo::ImageSurface> ytme = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, m_l + width, height);
+                       Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (ytme);
+                       cr->set_operator (Cairo::OPERATOR_SOURCE);
+                       cr->set_source_rgba (0, 0, 0, 1.0);
+                       cr->paint ();
+                       cr->rectangle (0, 0, m_l, height);
+                       cr->set_source_rgba (0, 0, 0, 0);
+                       cr->fill ();
+                       cr->set_operator (Cairo::OPERATOR_OVER);
+
+                       cr->set_line_width (1.0);
+                       for (int i = 0; i <= 4; ++i) {
+                               const float fract = (float) i / 4.0;
+                               // " XX:XX:XX.XXX"  [space/minus] 12 chars = 13.
+                               const float xalign = (i == 4) ? 1.0 : (i == 0) ? 1.0 / 13.0 : 7.0 / 13.0;
+
+                               char buf[16];
+                               AudioClock::print_minsec (start_off + file_length * fract,
+                                               buf, sizeof (buf), sample_rate);
+
+                               layout->set_text (buf);
+                               layout->get_pixel_size (w, h);
+                               cr->move_to (rint (m_l + width * fract - w * xalign), rint (.5 * (height - h)));
+                               cr->set_source_rgba (.9, .9, .9, 1.0);
+                               layout->show_in_cairo_context (cr);
+
+                               cr->set_source_rgba (.7, .7, .7, 1.0);
+                               cr->move_to (rint (m_l + width * fract) - .5, 0);
+                               cr->line_to (rint (m_l + width * fract) - .5, ceil  (height * .15));
+                               cr->move_to (rint (m_l + width * fract) - .5, floor (height * .85));
+                               cr->line_to (rint (m_l + width * fract) - .5, height);
+                               cr->stroke ();
+                       }
+
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallFont ());
+                       layout->set_text (_("Time"));
+                       cr->set_source_rgba (.9, .9, .9, 1.0);
+                       layout->get_pixel_size (w, h);
+                       cr->move_to (rint (.5 * (m_l - w)), rint (.5 * (height - h)));
+                       layout->show_in_cairo_context (cr);
+
+                       ytme->flush ();
+                       CimgArea *tm = manage (new CimgArea (ytme));
+                       vb->pack_start (*tm);
+               }
+
                {
-                       int w, h;
-                       Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (get_pango_context ());
+                       /* Draw Spectrum */
                        const size_t swh = sizeof (p->spectrum) / sizeof (float);
                        const size_t height = sizeof (p->spectrum[0]) / sizeof (float);
                        const size_t width = swh / height;
 
-                       Cairo::RefPtr<Cairo::ImageSurface> spec = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, width, height);
+                       Cairo::RefPtr<Cairo::ImageSurface> spec = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, m_l + width, height);
                        Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (spec);
-                       cr->rectangle (0, 0, width, height);
+                       cr->set_operator (Cairo::OPERATOR_SOURCE);
+                       cr->rectangle (0, 0, m_l, height);
+                       cr->set_source_rgba (0, 0, 0, 0);
+                       cr->fill ();
+                       cr->rectangle (m_l, 0, width, height);
                        cr->set_source_rgba (0, 0, 0, 1.0);
                        cr->fill ();
+                       cr->set_operator (Cairo::OPERATOR_OVER);
+
                        for (size_t x = 0 ; x < width; ++x) {
                                for (size_t y = 0 ; y < height; ++y) {
                                        const float pk = p->spectrum[x][y];
                                        ArdourCanvas::Color c = ArdourCanvas::hsva_to_color (252 - 260 * pk, .9, .3 + pk * .4);
                                        ArdourCanvas::set_source_rgba (cr, c);
-                                       cr->rectangle (x - .5, y - .5, 1, 1);
+                                       cr->rectangle (m_l + x - .5, y - .5, 1, 1);
                                        cr->fill ();
                                }
                        }
 
-                       layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
+                       // Unit
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
+                       layout->set_text (_("Hz"));
+                       layout->get_pixel_size (w, h);
+                       cr->move_to (rint (.5 * (m_l - h)), rint ((height + w) * .5));
+                       cr->set_source_rgba (.9, .9, .9, 1.0);
+                       cr->save ();
+                       cr->rotate (M_PI / -2.0);
+                       layout->show_in_cairo_context (cr);
+                       cr->restore ();
+
+                       // x-Axis
                        cr->set_line_width (1.0);
                        cr->set_dash (dashes, 2.0);
                        cr->set_line_cap (Cairo::LINE_CAP_ROUND);
-                       //PEAKANNOTATION (p->freq[0], _("50Hz"));
-                       PEAKANNOTATION (p->freq[1], _("100Hz"));
-                       PEAKANNOTATION (p->freq[2], _("500Hz"));
-                       PEAKANNOTATION (p->freq[3], _("1kHz"));
-                       PEAKANNOTATION (p->freq[4], _("5kHz"));
-                       PEAKANNOTATION (p->freq[5], _("10kHz"));
+
+                       layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
+                       //XAXISLABEL (p->freq[0], _("50Hz"));
+                       XAXISLABEL (p->freq[1], _("100"));
+                       XAXISLABEL (p->freq[2], _("500"));
+                       XAXISLABEL (p->freq[3], _("1K"));
+                       XAXISLABEL (p->freq[4], _("5K"));
+                       XAXISLABEL (p->freq[5], _("10K"));
 
                        spec->flush ();
                        CimgArea *sp = manage (new CimgArea (spec));
                        vb->pack_start (*sp);
                }
 
-               // TODO ellipsize tab-text
                pages.pages ().push_back (Notebook_Helpers::TabElem (*vb, Glib::path_get_basename (i->first)));
        }
 
@@ -409,13 +566,12 @@ ExportReport::ExportReport (Session* _session, StatusPtr s)
        pages.set_name ("ExportReportNotebook");
        pages.set_current_page (0);
 
-       get_vbox ()->set_spacing (12);
-       get_vbox ()->pack_start (pages);
+       get_vbox ()->set_spacing (4);
+       get_vbox ()->pack_start (pages, false, false);
 
        add_button (Stock::CLOSE, RESPONSE_ACCEPT);
        set_default_response (RESPONSE_ACCEPT);
        show_all ();
-       //pages.signal_switch_page ().connect (sigc::mem_fun (*this, &ExportReport::handle_page_change));
 }
 
 int