2 Copyright (C) 2008 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "export_timespan_selector.h"
23 #include "ardour_ui.h"
25 #include "ardour/tempo.h"
26 #include "ardour/location.h"
27 #include "ardour/types.h"
28 #include "ardour/session.h"
29 #include "ardour/export_handler.h"
30 #include "ardour/export_timespan.h"
32 #include "pbd/enumwriter.h"
33 #include "pbd/convert.h"
41 using namespace ARDOUR
;
45 ExportTimespanSelector::ExportTimespanSelector (ARDOUR::Session
* session
, ProfileManagerPtr manager
) :
47 time_format_label (_("Show Times as:"), Gtk::ALIGN_LEFT
)
49 set_session (session
);
51 option_hbox
.pack_start (time_format_label
, false, false, 0);
52 option_hbox
.pack_start (time_format_combo
, false, false, 6);
54 range_scroller
.add (range_view
);
56 pack_start (option_hbox
, false, false, 0);
57 pack_start (range_scroller
, true, true, 6);
61 Gtk::TreeModel::iterator iter
;
62 Gtk::TreeModel::Row row
;
64 /* Time format combo */
66 time_format_list
= Gtk::ListStore::create (time_format_cols
);
67 time_format_combo
.set_model (time_format_list
);
68 time_format_combo
.set_name ("PaddedButton");
70 iter
= time_format_list
->append();
72 row
[time_format_cols
.format
] = ExportProfileManager::Timecode
;
73 row
[time_format_cols
.label
] = _("Timecode");
75 iter
= time_format_list
->append();
77 row
[time_format_cols
.format
] = ExportProfileManager::MinSec
;
78 row
[time_format_cols
.label
] = _("Minutes:Seconds");
80 iter
= time_format_list
->append();
82 row
[time_format_cols
.format
] = ExportProfileManager::BBT
;
83 row
[time_format_cols
.label
] = _("Bars:Beats");
85 time_format_combo
.pack_start (time_format_cols
.label
);
86 time_format_combo
.set_active (0);
88 time_format_combo
.signal_changed().connect (sigc::mem_fun (*this, &ExportTimespanSelector::change_time_format
));
92 range_list
= Gtk::ListStore::create (range_cols
);
93 range_view
.set_model (range_list
);
94 range_view
.set_headers_visible (true);
97 ExportTimespanSelector::~ExportTimespanSelector ()
103 ExportTimespanSelector::add_range_to_selection (ARDOUR::Location
const * loc
)
105 TimespanPtr span
= _session
->get_export_handler()->add_timespan();
108 if (loc
== state
->session_range
.get()) {
110 } else if (loc
== state
->selection_range
.get()) {
113 id
= loc
->id().to_s();
116 span
->set_range (loc
->start(), loc
->end());
117 span
->set_name (loc
->name());
118 span
->set_range_id (id
);
119 state
->timespans
->push_back (span
);
123 ExportTimespanSelector::set_time_format_from_state ()
125 Gtk::TreeModel::Children::iterator tree_it
;
126 for (tree_it
= time_format_list
->children().begin(); tree_it
!= time_format_list
->children().end(); ++tree_it
) {
127 if (tree_it
->get_value (time_format_cols
.format
) == state
->time_format
) {
128 time_format_combo
.set_active (tree_it
);
134 ExportTimespanSelector::sync_with_manager ()
136 state
= manager
->get_timespans().front();
138 CriticalSelectionChanged();
142 ExportTimespanSelector::change_time_format ()
144 state
->time_format
= time_format_combo
.get_active()->get_value (time_format_cols
.format
);
146 for (Gtk::ListStore::Children::iterator it
= range_list
->children().begin(); it
!= range_list
->children().end(); ++it
) {
147 Location
* location
= it
->get_value (range_cols
.location
);
148 it
->set_value (range_cols
.label
, construct_label (location
));
149 it
->set_value (range_cols
.length
, construct_length (location
));
154 ExportTimespanSelector::construct_label (ARDOUR::Location
const * location
) const
160 framepos_t start_frame
= location
->start();
161 framepos_t end_frame
= location
->end();
163 switch (state
->time_format
) {
164 case AudioClock::BBT
:
165 start
= bbt_str (start_frame
);
166 end
= bbt_str (end_frame
);
169 case AudioClock::Timecode
:
170 start
= timecode_str (start_frame
);
171 end
= timecode_str (end_frame
);
174 case AudioClock::MinSec
:
175 start
= ms_str (start_frame
);
176 end
= ms_str (end_frame
);
179 case AudioClock::Frames
:
180 start
= to_string (start_frame
, std::dec
);
181 end
= to_string (end_frame
, std::dec
);
184 case AudioClock::Off
:
188 // label += _("from ");
190 // label += "<span color=\"#7fff7f\">";
192 // label += "</span>";
196 // label += "<span color=\"#7fff7f\">";
198 // label += "</span>";
204 ExportTimespanSelector::construct_length (ARDOUR::Location
const * location
) const
206 if (location
->length() == 0) {
212 switch (state
->time_format
) {
213 case AudioClock::BBT
:
214 s
<< bbt_str (location
->length ());
217 case AudioClock::Timecode
:
220 _session
->timecode_duration (location
->length(), tc
);
225 case AudioClock::MinSec
:
226 s
<< ms_str (location
->length ());
229 case AudioClock::Frames
:
230 s
<< location
->length ();
233 case AudioClock::Off
:
242 ExportTimespanSelector::bbt_str (framepos_t frames
) const
248 std::ostringstream oss
;
249 Timecode::BBT_Time time
;
250 _session
->bbt_time (frames
, time
);
252 print_padded (oss
, time
);
257 ExportTimespanSelector::timecode_str (framecnt_t frames
) const
263 std::ostringstream oss
;
266 _session
->timecode_time (frames
, time
);
268 oss
<< std::setfill('0') << std::right
<<
272 time
.minutes
<< ":" <<
274 time
.seconds
<< ":" <<
282 ExportTimespanSelector::ms_str (framecnt_t frames
) const
288 std::ostringstream oss
;
296 hrs
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
* 60.0f
));
297 left
-= (framecnt_t
) floor (hrs
* _session
->frame_rate() * 60.0f
* 60.0f
);
298 mins
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
));
299 left
-= (framecnt_t
) floor (mins
* _session
->frame_rate() * 60.0f
);
300 secs
= (int) floor (left
/ (float) _session
->frame_rate());
301 left
-= (framecnt_t
) floor (secs
* _session
->frame_rate());
302 sec_promilles
= (int) (left
* 1000 / (float) _session
->frame_rate() + 0.5);
304 oss
<< std::setfill('0') << std::right
<<
318 ExportTimespanSelector::update_range_name (std::string
const & path
, std::string
const & new_text
)
320 Gtk::TreeStore::iterator it
= range_list
->get_iter (path
);
321 it
->get_value (range_cols
.location
)->set_name (new_text
);
323 CriticalSelectionChanged();
326 /*** ExportTimespanSelectorSingle ***/
328 ExportTimespanSelectorSingle::ExportTimespanSelectorSingle (ARDOUR::Session
* session
, ProfileManagerPtr manager
, std::string range_id
) :
329 ExportTimespanSelector (session
, manager
),
332 range_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_NEVER
);
333 range_view
.append_column_editable ("Range", range_cols
.name
);
335 // Adjust selector height
336 int x_offset
, y_offset
, width
, height
;
337 Gtk::CellRenderer
* renderer
= *range_view
.get_column(0)->get_cell_renderers().begin();
338 renderer
->get_size (range_view
, x_offset
, y_offset
, width
, height
);
339 range_scroller
.set_size_request (-1, height
);
341 if (Gtk::CellRendererText
* renderer
= dynamic_cast<Gtk::CellRendererText
*> (range_view
.get_column_cell_renderer (0))) {
342 renderer
->signal_edited().connect (sigc::mem_fun (*this, &ExportTimespanSelectorSingle::update_range_name
));
345 Gtk::CellRendererText
* label_render
= Gtk::manage (new Gtk::CellRendererText());
346 Gtk::TreeView::Column
* label_col
= Gtk::manage (new Gtk::TreeView::Column ("Time Span", *label_render
));
347 label_col
->add_attribute (label_render
->property_markup(), range_cols
.label
);
348 range_view
.append_column (*label_col
);
350 range_view
.append_column ("Length", range_cols
.length
);
354 ExportTimespanSelectorSingle::fill_range_list ()
356 if (!state
) { return; }
359 if (!range_id
.compare (X_("session"))) {
360 id
= state
->session_range
->id().to_s();
361 } else if (!range_id
.compare (X_("selection"))) {
362 id
= state
->selection_range
->id().to_s();
368 state
->timespans
->clear();
370 Gtk::TreeModel::iterator iter
;
371 Gtk::TreeModel::Row row
;
372 for (LocationList::const_iterator it
= state
->ranges
->begin(); it
!= state
->ranges
->end(); ++it
) {
374 if (!(*it
)->id().to_s().compare (id
)) {
375 iter
= range_list
->append();
378 row
[range_cols
.location
] = *it
;
379 row
[range_cols
.selected
] = true;
380 row
[range_cols
.name
] = (*it
)->name();
381 row
[range_cols
.label
] = construct_label (*it
);
382 row
[range_cols
.length
] = construct_length (*it
);
384 add_range_to_selection (*it
);
390 set_time_format_from_state();
393 /*** ExportTimespanSelectorMultiple ***/
395 ExportTimespanSelectorMultiple::ExportTimespanSelectorMultiple (ARDOUR::Session
* session
, ProfileManagerPtr manager
) :
396 ExportTimespanSelector (session
, manager
)
398 range_scroller
.set_policy (Gtk::POLICY_AUTOMATIC
, Gtk::POLICY_AUTOMATIC
);
399 range_view
.append_column_editable ("", range_cols
.selected
);
400 range_view
.append_column_editable ("Range", range_cols
.name
);
402 if (Gtk::CellRendererToggle
* renderer
= dynamic_cast<Gtk::CellRendererToggle
*> (range_view
.get_column_cell_renderer (0))) {
403 renderer
->signal_toggled().connect (sigc::hide (sigc::mem_fun (*this, &ExportTimespanSelectorMultiple::update_selection
)));
405 if (Gtk::CellRendererText
* renderer
= dynamic_cast<Gtk::CellRendererText
*> (range_view
.get_column_cell_renderer (1))) {
406 renderer
->signal_edited().connect (sigc::mem_fun (*this, &ExportTimespanSelectorMultiple::update_range_name
));
409 Gtk::CellRendererText
* label_render
= Gtk::manage (new Gtk::CellRendererText());
410 Gtk::TreeView::Column
* label_col
= Gtk::manage (new Gtk::TreeView::Column ("Time Span", *label_render
));
411 label_col
->add_attribute (label_render
->property_markup(), range_cols
.label
);
412 range_view
.append_column (*label_col
);
414 range_view
.append_column ("Length", range_cols
.length
);
418 ExportTimespanSelectorMultiple::fill_range_list ()
420 if (!state
) { return; }
424 Gtk::TreeModel::iterator iter
;
425 Gtk::TreeModel::Row row
;
426 for (LocationList::const_iterator it
= state
->ranges
->begin(); it
!= state
->ranges
->end(); ++it
) {
428 iter
= range_list
->append();
431 row
[range_cols
.location
] = *it
;
432 row
[range_cols
.selected
] = false;
433 row
[range_cols
.name
] = (*it
)->name();
434 row
[range_cols
.label
] = construct_label (*it
);
435 row
[range_cols
.length
] = construct_length (*it
);
438 set_selection_from_state ();
442 ExportTimespanSelectorMultiple::set_selection_from_state ()
444 Gtk::TreeModel::Children::iterator tree_it
;
446 for (TimespanList::iterator it
= state
->timespans
->begin(); it
!= state
->timespans
->end(); ++it
) {
447 string id
= (*it
)->range_id();
448 for (tree_it
= range_list
->children().begin(); tree_it
!= range_list
->children().end(); ++tree_it
) {
449 Location
* loc
= tree_it
->get_value (range_cols
.location
);
451 if ((!id
.compare ("session") && loc
== state
->session_range
.get()) ||
452 (!id
.compare ("selection") && loc
== state
->selection_range
.get()) ||
453 (!id
.compare (loc
->id().to_s()))) {
454 tree_it
->set_value (range_cols
.selected
, true);
459 set_time_format_from_state();
463 ExportTimespanSelectorMultiple::update_selection ()
466 CriticalSelectionChanged ();
470 ExportTimespanSelectorMultiple::update_timespans ()
472 state
->timespans
->clear();
474 for (Gtk::TreeStore::Children::iterator it
= range_list
->children().begin(); it
!= range_list
->children().end(); ++it
) {
475 if (it
->get_value (range_cols
.selected
)) {
476 add_range_to_selection (it
->get_value (range_cols
.location
));