update Export Report GUI
[ardour.git] / gtk2_ardour / export_report.h
1 /*
2  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <cairo/cairo.h>
20 #include <gtkmm/notebook.h>
21 #include <gtkmm/togglebutton.h>
22
23 #include "gtkmm2ext/cairo_widget.h"
24 #include "gtkmm2ext/gui_thread.h"
25
26 #include "ardour/export_status.h"
27
28 #include "ardour_dialog.h"
29
30 class CimgArea : public CairoWidget
31 {
32 public:
33         CimgArea (Cairo::RefPtr<Cairo::ImageSurface> sf)
34                 : CairoWidget()
35                 , _surface(sf)
36         {
37                 set_size_request (sf->get_width (), sf->get_height ());
38         }
39
40 protected:
41         virtual void background (cairo_t* cr, cairo_rectangle_t* r) {
42                 cairo_set_source_surface (cr, _surface->cobj(), 0, 0);
43                 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
44                 cairo_paint (cr);
45         }
46
47         virtual void overlay (cairo_t* cr, cairo_rectangle_t* r) {}
48
49         virtual void render (cairo_t* cr, cairo_rectangle_t* r)
50         {
51                 cairo_rectangle (cr, r->x, r->y, r->width, r->height);
52                 cairo_clip (cr);
53                 background (cr, r);
54                 overlay (cr, r);
55         }
56
57         Cairo::RefPtr<Cairo::ImageSurface> _surface;
58 };
59
60 class CimgPlayheadArea : public CimgArea
61 {
62 public:
63         CimgPlayheadArea (Cairo::RefPtr<Cairo::ImageSurface> sf, float x0, float w, bool h = false)
64         : CimgArea (sf)
65         , _playhead(-1)
66         , _x0 (x0)
67         , _aw (w)
68         , _highlight (h)
69         {
70         }
71
72         void set_playhead (float pos) {
73                 if (rint (_playhead * _aw) == rint (pos * _aw)) {
74                         return;
75                 }
76                 if (_playhead == -1 || pos == -1) {
77                         set_dirty ();
78                 } else {
79                         invalidate (_playhead);
80                         invalidate (pos);
81                 }
82                 _playhead = pos;
83         }
84
85         sigc::signal<void, float> seek_playhead;
86
87 protected:
88
89         virtual void overlay (cairo_t* cr, cairo_rectangle_t* r) {
90                 if (_playhead > 0 && _playhead < 1.0 && _aw > 0) {
91                         if (_highlight) {
92                                 cairo_rectangle (cr, _x0, 0, _aw, _surface->get_height());
93                                 cairo_set_source_rgba (cr, .4, .4, .6, .4);
94                                 cairo_fill (cr);
95                         }
96
97                         const float x = _playhead * _aw;
98                         const float h = _surface->get_height();
99                         cairo_set_source_rgba (cr, 1, 0, 0, 1);
100                         cairo_set_line_width (cr, 1.5);
101                         cairo_move_to (cr, _x0 + x, 0);
102                         cairo_line_to (cr, _x0 + x, h);
103                         cairo_stroke (cr);
104                 }
105         }
106
107         bool on_button_press_event (GdkEventButton *ev) {
108                 CairoWidget::on_button_press_event (ev);
109                 if (ev->button == 1 && _aw > 0 && ev->x >= _x0 && ev->x <= _x0 + _aw) {
110                         seek_playhead (((float) ev->x - _x0) / (float)_aw);
111                 }
112                 return true;
113         }
114
115 private:
116         float _playhead;
117         float _x0, _aw;
118         bool _highlight;
119
120         void invalidate (float pos) {
121                 if (pos < 0 || pos > 1) { return; }
122                 const float x = pos * _aw;
123                 cairo_rectangle_t r;
124                 r.y = 0;
125                 r.x = _x0 + x - 1;
126                 r.width = 3;
127                 r.height = _surface->get_height();
128                 set_dirty (&r);
129         }
130 };
131
132 class CimgWaveArea : public CimgPlayheadArea
133 {
134 public:
135         CimgWaveArea (
136                         Cairo::RefPtr<Cairo::ImageSurface> sf,
137                         Cairo::RefPtr<Cairo::ImageSurface> sf_log,
138                         Cairo::RefPtr<Cairo::ImageSurface> sf_rect,
139                         Cairo::RefPtr<Cairo::ImageSurface> sf_logrec,
140                         float x0, float w)
141         : CimgPlayheadArea (sf, x0, w)
142         , _sf_log (sf_log)
143         , _sf_rect (sf_rect)
144         , _sf_logrec (sf_logrec)
145         , _logscale (false)
146         , _rectified (false)
147         {
148         }
149
150         void set_logscale (Gtk::ToggleButton *b) {
151                 bool en = b->get_active ();
152                 _logscale = en;
153                 set_dirty ();
154         }
155
156         void set_rectified (Gtk::ToggleButton *b) {
157                 bool en = b->get_active ();
158                 _rectified = en;
159                 set_dirty ();
160         }
161
162 protected:
163
164         virtual void background (cairo_t* cr, cairo_rectangle_t* r) {
165                 if (_logscale && _rectified) {
166                         cairo_set_source_surface (cr, _sf_logrec->cobj(), 0, 0);
167                 } else if (_logscale) {
168                         cairo_set_source_surface (cr, _sf_log->cobj(), 0, 0);
169                 } else if (_rectified) {
170                         cairo_set_source_surface (cr, _sf_rect->cobj(), 0, 0);
171                 } else {
172                         cairo_set_source_surface (cr, _surface->cobj(), 0, 0);
173                 }
174                 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
175                 cairo_paint (cr);
176         }
177
178 private:
179         Cairo::RefPtr<Cairo::ImageSurface> _sf_log;
180         Cairo::RefPtr<Cairo::ImageSurface> _sf_rect;
181         Cairo::RefPtr<Cairo::ImageSurface> _sf_logrec;
182         bool _logscale;
183         bool _rectified;
184 };
185
186 class ExportReport : public ArdourDialog
187 {
188 public:
189         typedef boost::shared_ptr<ARDOUR::ExportStatus> StatusPtr;
190         ExportReport (ARDOUR::Session*, StatusPtr);
191         int run ();
192
193 private:
194         void draw_waveform (Cairo::RefPtr<Cairo::ImageSurface>& wave,
195                         ARDOUR::ExportAnalysisPtr, uint32_t, int, size_t, int, int, bool, bool);
196
197         void open_folder (std::string);
198         void audition (std::string, unsigned int, int);
199         void stop_audition ();
200         void play_audition ();
201         void audition_active (bool);
202         void audition_seek (int, float);
203         void audition_progress (ARDOUR::framecnt_t, ARDOUR::framecnt_t);
204         void on_switch_page (GtkNotebookPage*, guint page_num);
205
206         StatusPtr        status;
207         Gtk::Notebook    pages;
208         ARDOUR::Session* _session;
209         Gtk::Button*     stop_btn;
210         Gtk::Button*     play_btn;
211         PBD::ScopedConnectionList auditioner_connections;
212
213         struct AuditionInfo {
214                 AuditionInfo (std::string p, unsigned int c) : path (p), channels (c) {}
215                 AuditionInfo () : channels (0) {}
216                 std::string  path;
217                 unsigned int channels;
218         };
219
220         std::map<int, std::list<CimgPlayheadArea*> > timeline;
221         std::map<int, AuditionInfo> files;
222
223         int _audition_num;
224         int _page_num;
225 };