+ do {
+ int i = ArdourDialog::run ();
+ if (i == Gtk::RESPONSE_DELETE_EVENT || i == RESPONSE_CLOSE) {
+ break;
+ }
+ } while (1);
+
+ if (_session) {
+ _session->cancel_audition();
+ }
+ return RESPONSE_CLOSE;
+}
+
+void
+ExportReport::open_folder (std::string p)
+{
+ PBD::open_folder (Glib::path_get_dirname(p));
+}
+
+void
+ExportReport::audition_active (bool active)
+{
+ if (!stop_btn || !play_btn) {
+ return;
+ }
+ stop_btn->set_sensitive (active);
+ play_btn->set_sensitive (!active);
+
+ if (!active && _audition_num == _page_num && timeline.find (_audition_num) != timeline.end ()) {
+ for (std::list<CimgPlayheadArea*>::const_iterator i = timeline[_audition_num].begin();
+ i != timeline[_audition_num].end();
+ ++i) {
+ (*i)->set_playhead (-1);
+ }
+ }
+
+ if (_audition_num >= 0 ) {
+ Widget *page = pages.get_nth_page (_audition_num);
+ HBox *box = static_cast<Gtk::HBox*> (pages.get_tab_label (*page));
+ if (!active) {
+ (*(box->get_children().begin()))->hide ();
+ } else {
+ (*(box->get_children().begin()))->show ();
+ }
+ }
+
+ if (!active) {
+ _audition_num = -1;
+ }
+}
+
+void
+ExportReport::audition (std::string path, unsigned n_chn, int page)
+{
+ assert (_session);
+ _session->cancel_audition();
+
+ if (n_chn ==0) { return; }
+
+ /* can't really happen, unless the user replaces the file while the dialog is open.. */
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+ PBD::warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
+ return;
+ }
+ if (SMFSource::valid_midi_file (path)) { return; }
+
+ boost::shared_ptr<Region> r;
+ SourceList srclist;
+ boost::shared_ptr<AudioFileSource> afs;
+ bool old_sbp = AudioSource::get_build_peakfiles ();
+
+ /* don't even think of building peakfiles for these files */
+ AudioSource::set_build_peakfiles (false);
+
+ for (unsigned int n = 0; n < n_chn; ++n) {
+ try {
+ afs = boost::dynamic_pointer_cast<AudioFileSource> (
+ SourceFactory::createExternal (DataType::AUDIO, *_session,
+ path, n,
+ Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
+ if (afs->sample_rate() != _session->nominal_frame_rate()) {
+ boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, ARDOUR::SrcGood));
+ srclist.push_back(sfs);
+ } else {
+ srclist.push_back(afs);
+ }
+ } catch (failed_constructor& err) {
+ PBD::error << _("Could not access soundfile: ") << path << endmsg;
+ AudioSource::set_build_peakfiles (old_sbp);
+ return;
+ }
+ }
+
+ AudioSource::set_build_peakfiles (old_sbp);
+
+ if (srclist.empty()) {
+ return;
+ }
+
+ afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
+ std::string rname = region_name_from_path (afs->path(), false);
+
+ PBD::PropertyList plist;
+
+ plist.add (ARDOUR::Properties::start, 0);
+ plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
+ plist.add (ARDOUR::Properties::name, rname);
+ plist.add (ARDOUR::Properties::layer, 0);
+
+ r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
+
+ r->set_position(0);
+ _session->audition_region(r);
+ _audition_num = page;
+}
+
+void
+ExportReport::play_audition ()
+{
+ if (_audition_num >= 0 || !_session) { return; }
+ if (files.find (_page_num) == files.end()) { return; }
+ audition (files[_page_num].path, files[_page_num].channels, _page_num);
+}
+
+void
+ExportReport::stop_audition ()
+{
+ if (_audition_num == _page_num && timeline.find (_audition_num) != timeline.end ()) {
+ for (std::list<CimgPlayheadArea*>::const_iterator i = timeline[_audition_num].begin();
+ i != timeline[_audition_num].end();
+ ++i) {
+ (*i)->set_playhead (-1);
+ }
+ }
+ if (_session) {
+ _session->cancel_audition();
+ }
+}
+
+void
+ExportReport::on_switch_page (GtkNotebookPage*, guint page_num)
+{
+ if (_audition_num == _page_num) {
+ for (std::list<CimgPlayheadArea*>::const_iterator i = timeline[_audition_num].begin();
+ i != timeline[_audition_num].end();
+ ++i) {
+ (*i)->set_playhead (-1);
+ }
+ }
+ _page_num = page_num;
+}
+
+void
+ExportReport::audition_progress (framecnt_t pos, framecnt_t len)
+{
+ if (_audition_num == _page_num && timeline.find (_audition_num) != timeline.end ()) {
+ const float p = (float)pos / len;
+ for (std::list<CimgPlayheadArea*>::const_iterator i = timeline[_audition_num].begin();
+ i != timeline[_audition_num].end();
+ ++i) {
+ (*i)->set_playhead (p);
+ }
+ }
+}
+
+void
+ExportReport::audition_seek (int page, float pos)
+{
+ if (_audition_num == page && _session) {
+ _session->the_auditioner()->seek_to_percent (100.f * pos);
+ }
+}
+
+void
+ExportReport::on_logscale_toggled (Gtk::ToggleButton* b)
+{
+ bool en = b->get_active ();
+ for (std::list<CimgWaveArea*>::iterator i = waves.begin (); i != waves.end (); ++i) {
+ (*i)->set_logscale (en);
+ }
+}
+
+void
+ExportReport::on_rectivied_toggled (Gtk::ToggleButton* b)
+{
+ bool en = b->get_active ();
+ for (std::list<CimgWaveArea*>::iterator i = waves.begin (); i != waves.end (); ++i) {
+ (*i)->set_rectified (en);
+ }
+}
+
+void
+ExportReport::draw_waveform (Cairo::RefPtr<Cairo::ImageSurface>& wave, ExportAnalysisPtr p, uint32_t c, int m_l, size_t width, int anw, int height_2, bool log, bool rect)
+{
+ int w, h;
+ Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (get_pango_context ());
+ const float ht = 2.f * height_2;
+
+ std::vector<double> dashes;
+ dashes.push_back (3.0);
+ dashes.push_back (5.0);
+
+ wave = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, m_l + width, ht);
+ Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (wave);
+ cr->set_operator (Cairo::OPERATOR_SOURCE);
+ cr->rectangle (0, 0, m_l, ht);
+ cr->set_source_rgba (0, 0, 0, 0);
+ cr->fill ();
+ cr->rectangle (m_l, 0, width, ht);
+ 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);
+
+ // -1dB range
+ float clip_top;
+ float clip_bot;
+
+ if (rect) {
+ clip_bot = ht;
+
+ if (log) {
+ clip_top = ht * (1.f - alt_log_meter (-1));
+ for (size_t x = 0 ; x < width; ++x) {
+ const float v = alt_log_meter (fast_coefficient_to_dB (std::max (fabsf (p->peaks[c][x].max), fabsf (p->peaks[c][x].min))));
+ cr->move_to (m_l + x - .5, ht - ht * v);
+ cr->line_to (m_l + x - .5, ht);
+ }
+ cr->stroke ();
+ } else {
+ clip_top = ht * (1.f - dB_to_coefficient (-1));
+ for (size_t x = 0 ; x < width; ++x) {
+ const float v = std::max (fabsf (p->peaks[c][x].max), fabsf (p->peaks[c][x].min));
+ cr->move_to (m_l + x - .5, ht - ht * v);
+ cr->line_to (m_l + x - .5, ht);
+ }
+ cr->stroke ();
+ }
+ } else {
+ if (log) {
+ clip_top = height_2 - height_2 * alt_log_meter (-1);
+ clip_bot = height_2 + height_2 * alt_log_meter (-1);
+ for (size_t x = 0 ; x < width; ++x) {
+ float pmax, pmin;
+ if (p->peaks[c][x].max > 0) {
+ pmax = alt_log_meter (fast_coefficient_to_dB (p->peaks[c][x].max));
+ } else {
+ pmax = -alt_log_meter (fast_coefficient_to_dB (-p->peaks[c][x].max));
+ }
+
+ if (p->peaks[c][x].min > 0) {
+ pmin = alt_log_meter (fast_coefficient_to_dB (p->peaks[c][x].min));
+ } else {
+ pmin = -alt_log_meter (fast_coefficient_to_dB (-p->peaks[c][x].min));
+ }
+ cr->move_to (m_l + x - .5, height_2 - height_2 * pmax);
+ cr->line_to (m_l + x - .5, height_2 - height_2 * pmin);
+ }
+ cr->stroke ();
+ } else {
+ clip_top = height_2 - height_2 * dB_to_coefficient (-1);
+ clip_bot = height_2 + height_2 * dB_to_coefficient (-1);
+ for (size_t x = 0 ; x < width; ++x) {
+ 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 ();
+ }
+ }
+
+ // >= 0dBFS
+ cr->set_source_rgba (1.0, 0, 0, 1.0);
+ for (size_t x = 0 ; x < width; ++x) {
+ if (p->peaks[c][x].max >= 1.0) {
+ cr->move_to (m_l + x - .5, 0);
+ cr->line_to (m_l + x - .5, clip_top);
+ }
+ if (p->peaks[c][x].min <= -1.0) {
+ cr->move_to (m_l + x - .5, clip_bot);
+ cr->line_to (m_l + x - .5, ht);
+ }
+ }
+ cr->stroke ();
+
+ // >= -1dBTP (coeff >= .89125, libs/vamp-plugins/TruePeak.cpp)
+ cr->set_source_rgba (1.0, 0.7, 0, 0.7);
+ for (std::set<framepos_t>::const_iterator i = p->truepeakpos[c].begin (); i != p->truepeakpos[c].end (); ++i) {
+ cr->move_to (m_l + (*i) - .5, clip_top);
+ cr->line_to (m_l + (*i) - .5, clip_bot);
+ cr->stroke ();
+ }
+
+ if (!rect) {
+ // zero line
+ cr->set_source_rgba (.3, .3, .3, 0.7);
+ cr->move_to (m_l + 0, height_2 - .5);
+ cr->line_to (m_l + width, height_2 - .5);
+ cr->stroke ();
+ }
+
+ // Unit
+ layout->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
+ layout->set_alignment (Pango::ALIGN_LEFT);
+ layout->set_text (_("dBFS"));
+ layout->get_pixel_size (w, h);
+ cr->move_to (rint (m_l - h - anw - 10), 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 ();
+
+ // x-Axis
+ cr->set_line_width (1.0);
+ cr->set_dash (dashes, 2.0);
+ cr->set_line_cap (Cairo::LINE_CAP_ROUND);
+
+ layout->set_font_description (UIConfiguration::instance ().get_SmallMonospaceFont ());
+
+ if (rect) {
+ if (log) {
+ XAXISLABEL ((ht - ht * alt_log_meter (-36)), _("-36"));
+ XAXISLABEL ((ht - ht * alt_log_meter (-18)), _("-18"));
+ XAXISLABEL ((ht - ht * alt_log_meter (-9)), _("-9"));
+ XAXISLABEL ((ht - ht * alt_log_meter (-3)), _("-3"));
+ } else {
+ XAXISLABEL ((ht - ht * .1259), _("-18"));
+ XAXISLABEL ((ht - ht * .3548), _("-9"));
+ XAXISLABEL ((ht - ht * .7079), _("-3"));
+ }
+ } else {
+ if (log) {
+ XAXISLABEL ((height_2 - height_2 * alt_log_meter (-18)), _("-18"));
+ XAXISLABEL ((height_2 - height_2 * alt_log_meter (-9)), _("-9"));
+ XAXISLABEL ((height_2 - height_2 * alt_log_meter (-3)), _("-3"));
+ XAXISLABEL ((height_2 + height_2 * alt_log_meter (-18)), _("-18"));
+ XAXISLABEL ((height_2 + height_2 * alt_log_meter (-9)), _("-9"));
+ XAXISLABEL ((height_2 + height_2 * alt_log_meter (-3)), _("-3"));
+ } else {
+ 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 ();