[ardour-dev] new feature: export all ranges
Andre Raue
dawng at raue.info
Tue Jan 3 02:46:20 PST 2006
Hello,
during the last few weaks I have been implementing a new feature in
ardour. This makes it possible to export all ranges marked with range
markers to separate files in a row. Below you will find the following
information:
1) How is it expected to work / what should it do?
2) limitations / requirements
3) Status of developement
4) Next steps
5) cvs diff against 0.99 for requirements mentioned in 2)
6) cvs diff against 0.99 for the current alpha-version (new files
excluded, 5) included)
7) diff of new file session_export_dialog.cc against export_dialog.cc
8) diff of new file session_export_dialog.h against export_dialog.h
I would be happy about some constructive criticisim. So - if you have
some comments or ideas concerning this feature/code, please don't
hesitate to utter them. In addition it would be great if you could
implement the changes explained in 2) and 5) in ardour 2.0, as I need
those for this feature.
If somebody would like to have a complete version of the changed/new
files, please let me know. In this case I will provide them for download.
Last but not least I would like to thank Tommi Sakari Uimonen and Taybin
Rutkin for helping me getting started.
1) How is it expected to work / what should it do?
-------------------------------------------------------
a) mark ranges within ardour as usual
b) select menu item "Session - Export - Export all ranges..."
c) a dialog similar to the usual export-dialog appears
d) define a destination directory and some export-attributes like
sampling-rate etc.
e) push start-button
f) all ranges marked by range markers get exported to the destination
directory. Each range results in a separate file. File names are the
same as range names.
g) export-dialog gets closed
2) limitations / requirements
-------------------------------
Using the current code, I found no safe way, to decide wether a Location
object is a range or not. What I found is "enum Flags" in location.h.
Using these flags you can for example decide if a Location object
IsMark, IsAutoPunch, ... But there is no flag IsRange. Thus I decided to
add this flag. This led to changes in the files editor_mouse.cc,
location_ui.cc and location.h. You can find these changes in 5). These
changes are the requirements I need for the implemented feature.
The disadvantage of this solution is: Ranges defined with prior versions
of ardour won't be exported using this feature, as they are not flagged
as ranges. An idea for solving this problem is to add this flag for all
Location objects with different start- and end-frame when opening a
session that has been saved with a prior ardour-version. Is this
possible? Does the ardour-version get stored in the session file? Are
ranges the only locations with different start- and end-frame in 0.99?
3) Status of developement
-----------------------------
As I based my development on ardour 0.99, I decided to halt development
when reaching a proof of concept status until ardour 2.0 will be
released. This is the point where I am. Thus I concider the current
version as an alpha-version.
It works but you have to know what you do and it still has some bugs. E.g.:
- the name, that you fill in for the destination-directory must not have
a '/' at the end
- the destination-directory get's not checked for existence
- all files get the ending '.wav' even if you chose a different file-format
- the progress bar starts at 0% and ends at 100% for each single range
instead of starting by 0% for the first range and ending at 100% for the
last one
So, if you find some more bugs, please let me know.
4) Next steps
---------------
After getting access to the 2.0-version of the ExportDialog class I will
go on with development. My idea is to do some refactoring so that there
is one base class and three derived classes for export-dialogs. One for
exporting a region, one for exporting a single range and one for
exporting all ranges. The bugs mentioned in 3) will be removed. I hope
to be able to provide a complete version with ardour 2.0 or the version
that follows 2.0.
Please let me know, when the 2.0-version of the ExportDialog class is ready.
5) cvs diff against 0.99 for requirements mentioned in 2)
--------------------------------------------------------------
Index: gtk_ardour/editor_mouse.cc
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/editor_mouse.cc,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
4205c4205
< newloc = new Location(temp_location->start(),
temp_location->end(), "unnamed");
---
> newloc = new Location(temp_location->start(),
temp_location->end(), "unnamed", Location::IsRange);
Index: gtk_ardour/location_ui.cc
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/location_ui.cc,v
retrieving revision 1.1
retrieving revision 1.4
diff -r1.1 -r1.4
813c813
< Location *location = new Location (where, where, "unnamed");
---
> Location *location = new Location (where, where, "unnamed",
Location::IsRange);
886d885
<
Index: libs/ardour/ardour/location.h
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/libs/ardour/ardour/location.h,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
53c53,54
< IsEnd = 0x20
---
> IsEnd = 0x20,
> IsRange = 0x40
97a99
> bool is_range() { return _flags & IsRange; }
6) cvs diff against 0.99 for the current alpha-version (new files excluded)
--------------------------------------------------------------------------------
Index: gtk_ardour/SConscript
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/SConscript,v
retrieving revision 1.1
retrieving revision 1.2
diff -r1.1 -r1.2
94a95
> session_export_dialog.cc
Index: gtk_ardour/ardour_ui_ed.cc
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/ardour_ui_ed.cc,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
134a135
> export_items.push_back (MenuElem (_("Export all ranges..."), slot
(*editor, &PublicEditor::export_ranges)));
315d315
<
Index: gtk_ardour/editor.h
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/editor.h,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
93a94
> class SessionExportDialog;
230a232
> void export_ranges();
1596a1599
> SessionExportDialog *session_export_dialog;
Index: gtk_ardour/editor_export_audio.cc
===================================================================
RCS file:
/home/andre/cvs_repository/Ardour/gtk_ardour/editor_export_audio.cc,v
retrieving revision 1.1
retrieving revision 1.4
diff -r1.1 -r1.4
23a24
> #include "session_export_dialog.h"
69a71,84
> Editor::export_ranges()
> {
> if (session) {
> if (session_export_dialog == 0) {
> session_export_dialog = new SessionExportDialog(*this);
> }
>
> session_export_dialog->connect_to_session (session);
> session_export_dialog->set_range (0,
session->current_end_frame());
> session_export_dialog->start_export();
> }
> }
>
> void
Index: gtk_ardour/editor_mouse.cc
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/editor_mouse.cc,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
4205c4205
< newloc = new Location(temp_location->start(),
temp_location->end(), "unnamed");
---
> newloc = new Location(temp_location->start(),
temp_location->end(), "unnamed", Location::IsRange);
Index: gtk_ardour/location_ui.cc
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/location_ui.cc,v
retrieving revision 1.1
retrieving revision 1.4
diff -r1.1 -r1.4
813c813
< Location *location = new Location (where, where, "unnamed");
---
> Location *location = new Location (where, where, "unnamed",
Location::IsRange);
886d885
<
Index: gtk_ardour/public_editor.h
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/gtk_ardour/public_editor.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -r1.1 -r1.2
82a83
> virtual void export_ranges() = 0;
Index: libs/ardour/ardour/location.h
===================================================================
RCS file: /home/andre/cvs_repository/Ardour/libs/ardour/ardour/location.h,v
retrieving revision 1.1
retrieving revision 1.3
diff -r1.1 -r1.3
53c53,54
< IsEnd = 0x20
---
> IsEnd = 0x20,
> IsRange = 0x40
97a99
> bool is_range() { return _flags & IsRange; }
7) diff of new file session_export_dialog.cc against export_dialog.cc
---------------------------------------------------------------------------
40c40
< #include "export_dialog.h"
---
> #include "session_export_dialog.h"
51,54c51,56
< GdkPixmap* ExportDialog::check_pixmap = 0;
< GdkPixmap* ExportDialog::check_mask = 0;
< GdkPixmap* ExportDialog::empty_pixmap = 0;
< GdkPixmap* ExportDialog::empty_mask = 0;
---
> void frames_to_cd_frames_string (char*, jack_nframes_t, jack_nframes_t);
>
> GdkPixmap* SessionExportDialog::check_pixmap = 0;
> GdkPixmap* SessionExportDialog::check_mask = 0;
> GdkPixmap* SessionExportDialog::empty_pixmap = 0;
> GdkPixmap* SessionExportDialog::empty_mask = 0;
102c104
< ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
---
> SessionExportDialog::SessionExportDialog(PublicEditor& e, AudioRegion* r)
159c161
< master_selector.button_press_event.connect (slot (*this,
&ExportDialog::master_selector_button_press_event));
---
> master_selector.button_press_event.connect (slot (*this,
&SessionExportDialog::master_selector_button_press_event));
171c173
< track_selector.button_press_event.connect (slot (*this,
&ExportDialog::track_selector_button_press_event));
---
> track_selector.button_press_event.connect (slot (*this,
&SessionExportDialog::track_selector_button_press_event));
217c219
< track_selector_button.clicked.connect (slot (*this,
&ExportDialog::track_selector_button_click));
---
> track_selector_button.clicked.connect (slot (*this,
&SessionExportDialog::track_selector_button_click));
381,383c383,385
< delete_event.connect (slot (*this, &ExportDialog::window_closed));
< ok_button.clicked.connect (slot (*this, &ExportDialog::do_export));
< cancel_button.clicked.connect (slot (*this,
&ExportDialog::end_dialog));
---
> delete_event.connect (slot (*this,
&SessionExportDialog::window_closed));
> ok_button.clicked.connect (slot (*this,
&SessionExportDialog::do_export));
> cancel_button.clicked.connect (slot (*this,
&SessionExportDialog::end_dialog));
386c388
< file_browse_button.clicked.connect (slot (*this,
&ExportDialog::initiate_browse));
---
> file_browse_button.clicked.connect (slot (*this,
&SessionExportDialog::initiate_browse));
388,392c390,394
< channel_count_combo.get_popwin()->unmap_event.connect (slot
(*this, &ExportDialog::channels_chosen));
< bitdepth_format_combo.get_popwin()->unmap_event.connect (slot
(*this, &ExportDialog::bitdepth_chosen));
< header_format_combo.get_popwin()->unmap_event.connect (slot
(*this, &ExportDialog::header_chosen));
< sample_rate_combo.get_popwin()->unmap_event.connect (slot (*this,
&ExportDialog::sample_rate_chosen));
< cue_file_combo.get_popwin()->unmap_event.connect (slot (*this,
&ExportDialog::cue_file_type_chosen));
---
> channel_count_combo.get_popwin()->unmap_event.connect (slot
(*this, &SessionExportDialog::channels_chosen));
> bitdepth_format_combo.get_popwin()->unmap_event.connect (slot
(*this, &SessionExportDialog::bitdepth_chosen));
> header_format_combo.get_popwin()->unmap_event.connect (slot
(*this, &SessionExportDialog::header_chosen));
> sample_rate_combo.get_popwin()->unmap_event.connect (slot (*this,
&SessionExportDialog::sample_rate_chosen));
> cue_file_combo.get_popwin()->unmap_event.connect (slot (*this,
&SessionExportDialog::cue_file_type_chosen));
395c397
< ExportDialog::~ExportDialog()
---
> SessionExportDialog::~SessionExportDialog()
403c405
< ExportDialog::connect_to_session (Session *s)
---
> SessionExportDialog::connect_to_session (Session *s)
438c440
< ExportDialog::set_state()
---
> SessionExportDialog::set_state()
554c556
< ExportDialog::save_state()
---
> SessionExportDialog::save_state()
592c594
< ExportDialog::set_range (jack_nframes_t start, jack_nframes_t end)
---
> SessionExportDialog::set_range (jack_nframes_t start, jack_nframes_t end)
604c606
< ExportDialog::progress_timeout ()
---
> SessionExportDialog::progress_timeout ()
611c613
< ExportDialog::_export_region_thread (void *arg)
---
> SessionExportDialog::_export_region_thread (void *arg)
615c617
< static_cast<ExportDialog*>(arg)->export_region ();
---
> static_cast<SessionExportDialog*>(arg)->export_region ();
620c622
< ExportDialog::export_region ()
---
> SessionExportDialog::export_region ()
625,639d626
< void
< frames_to_cd_frames_string (char* buf, jack_nframes_t when,
jack_nframes_t fr)
< {
<
< long unsigned int remainder;
< int mins, secs, frames;
<
< mins = when / (60 * fr);
< remainder = when - (mins * 60 * fr);
< secs = remainder / fr;
< remainder -= secs * fr;
< frames = remainder / (fr / 75);
< sprintf (buf, " %02d:%02d:%02d", mins, secs, frames);
<
< }
648c635
< ExportDialog::export_toc_file (Locations::LocationList& locations,
const string& path)
---
> SessionExportDialog::export_toc_file (Locations::LocationList&
locations, const string& path)
771c758
< ExportDialog::export_cue_file (Locations::LocationList& locations,
const string& path)
---
> SessionExportDialog::export_cue_file (Locations::LocationList&
locations, const string& path)
894c881
< ExportDialog::do_export_cd_markers (const string& path,const string&
cuefile_type)
---
> SessionExportDialog::do_export_cd_markers (const string& path,const
string& cuefile_type)
897c884
< session->locations()->apply (*this,
&ExportDialog::export_toc_file, path);
---
> session->locations()->apply (*this,
&SessionExportDialog::export_toc_file, path);
899c886
< session->locations()->apply (*this,
&ExportDialog::export_cue_file, path);
---
> session->locations()->apply (*this,
&SessionExportDialog::export_cue_file, path);
904,906c891,894
< void
< ExportDialog::do_export ()
< {
---
> /*
> initializes spec, so that the export of a range can start
> */
> void SessionExportDialog::initSpec(AudioExportSpecification &spec){
908,921d895
<
< ok_button.set_sensitive(false);
< save_state();
<
< if (cue_file_combo.get_entry()->get_text () != _("None")) {
< do_export_cd_markers (file_entry.get_text(),
cue_file_combo.get_entry()->get_text ());
< }
<
< if (cuefile_only_checkbox.get_active()) {
< end_dialog ();
< return;
< }
<
< set_modal (true);
923d896
< spec.path = file_entry.get_text();
1048a1022
> }
1050,1051c1024,1028
< progress_connection = Main::timeout.connect (slot (*this,
&ExportDialog::progress_timeout), 100);
< cancel_label.set_text (_("Stop Export"));
---
> void
> SessionExportDialog::do_export ()
> {
> ok_button.set_sensitive(false);
> save_state();
1053,1059c1030,1031
< if (!audio_region) {
< if (session->start_audio_export (spec)) {
< goto out;
< }
< } else {
< pthread_t thr;
< pthread_create_and_store ("region export", &thr, 0,
ExportDialog::_export_region_thread, this);
---
> if (cue_file_combo.get_entry()->get_text () != _("None")) {
> do_export_cd_markers (file_entry.get_text(),
cue_file_combo.get_entry()->get_text ());
1062,1067c1034,1054
< gtk_main_iteration ();
< while (spec.running) {
< if (gtk_events_pending()) {
< gtk_main_iteration ();
< } else {
< usleep (10000);
---
> if (cuefile_only_checkbox.get_active()) {
> end_dialog ();
> return;
> }
>
> set_modal (true);
>
> progress_connection = Main::timeout.connect (slot (*this,
&SessionExportDialog::progress_timeout), 100);
> cancel_label.set_text (_("Stop Export"));
>
> session->locations()->apply(*this,
&SessionExportDialog::process_audioranges_export, spec);
> #if 0
> goto out;
> #endif
>
> gtk_main_iteration();
> while(spec.running){
> if(gtk_events_pending()){
> gtk_main_iteration();
> }else {
> usleep(10000);
1077,1078c1064,1065
< void
< ExportDialog::end_dialog ()
---
> void
>
SessionExportDialog::process_audioranges_export(Locations::LocationList&
locations, ARDOUR::AudioExportSpecification& spec)
1079a1067,1101
> Locations::LocationList::iterator locationIter;
>
> //XXX: ToDo: check somewhere if the given destination path is
existing
> // and if it is a path
>
> for (locationIter = locations.begin(); locationIter !=
locations.end(); ++locationIter) {
> Location *currentLocation = (*locationIter);
>
> if(currentLocation->is_range()){
> //XXX: ToDo: check if file_entry has "/" at the end
> initSpec(spec);
> spec.path = file_entry.get_text() + '/' +
currentLocation->name() + ".wav";
> spec.start_frame = currentLocation->start();
> spec.end_frame = currentLocation->end();
>
> session->request_locate(spec.start_frame, false);
>
> //XXX: ToDo: what to do when start_audio_export fails?
before it was
> // goto out; in method do_export
> session->start_audio_export(spec);
>
> // wait until export of this range finished
> gtk_main_iteration();
> while(spec.running){
> if(gtk_events_pending()){
> gtk_main_iteration();
> }else {
> usleep(10000);
> }
> }
>
> session->engine().freewheel (false);
> }
> }
> }
1080a1103,1106
>
> void
> SessionExportDialog::end_dialog ()
> {
1106c1132
< ExportDialog::start_export ()
---
> SessionExportDialog::start_export ()
1142c1168
< ExportDialog::header_chosen (GdkEventAny* ignored)
---
> SessionExportDialog::header_chosen (GdkEventAny* ignored)
1153c1179
< ExportDialog::bitdepth_chosen (GdkEventAny* ignored)
---
> SessionExportDialog::bitdepth_chosen (GdkEventAny* ignored)
1172c1198
< ExportDialog::cue_file_type_chosen (GdkEventAny* ignored)
---
> SessionExportDialog::cue_file_type_chosen (GdkEventAny* ignored)
1184c1210
< ExportDialog::sample_rate_chosen (GdkEventAny* ignored)
---
> SessionExportDialog::sample_rate_chosen (GdkEventAny* ignored)
1215c1241
< ExportDialog::channels_chosen (GdkEventAny* ignored)
---
> SessionExportDialog::channels_chosen (GdkEventAny* ignored)
1293c1319
< ExportDialog::track_selector_button_press_event (GdkEventButton* ev)
---
> SessionExportDialog::track_selector_button_press_event
(GdkEventButton* ev)
1317c1343
< ExportDialog::master_selector_button_press_event (GdkEventButton* ev)
---
> SessionExportDialog::master_selector_button_press_event
(GdkEventButton* ev)
1341c1367
< ExportDialog::window_closed (GdkEventAny *ignored)
---
> SessionExportDialog::window_closed (GdkEventAny *ignored)
1347c1373
< ExportDialog::initiate_browse ()
---
> SessionExportDialog::initiate_browse ()
1353,1356c1379,1382
< file_selector->get_cancel_button()->clicked.connect (bind
(slot (*this, &ExportDialog::finish_browse), -1));
< file_selector->get_ok_button()->clicked.connect (bind (slot
(*this, &ExportDialog::finish_browse), 1));
< file_selector->map_event.connect (bind (slot (*this,
&ExportDialog::change_focus_policy), true));
< file_selector->unmap_event.connect (bind (slot (*this,
&ExportDialog::change_focus_policy), false));
---
> file_selector->get_cancel_button()->clicked.connect (bind
(slot (*this, &SessionExportDialog::finish_browse), -1));
> file_selector->get_ok_button()->clicked.connect (bind (slot
(*this, &SessionExportDialog::finish_browse), 1));
> file_selector->map_event.connect (bind (slot (*this,
&SessionExportDialog::change_focus_policy), true));
> file_selector->unmap_event.connect (bind (slot (*this,
&SessionExportDialog::change_focus_policy), false));
1362c1388
< ExportDialog::change_focus_policy (GdkEventAny *ev, bool yn)
---
> SessionExportDialog::change_focus_policy (GdkEventAny *ev, bool yn)
1369c1395
< ExportDialog::finish_browse (int status)
---
> SessionExportDialog::finish_browse (int status)
1384c1410
< ExportDialog::track_selector_button_click ()
---
> SessionExportDialog::track_selector_button_click ()
8) diff of new file session_export_dialog.h against export_dialog.h
--------------------------------------------------------------------------
20,21c20,21
< #ifndef __ardour_export_dialog_h__
< #define __ardour_export_dialog_h__
---
> #ifndef __ardour_session_export_dialog_h__
> #define __ardour_session_export_dialog_h__
37c37
< class ExportDialog : public ArdourDialog
---
> class SessionExportDialog : public ArdourDialog
40,41c40,41
< ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0);
< ~ExportDialog ();
---
> SessionExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0);
> ~SessionExportDialog ();
112c112,113
< void do_export_cd_markers (const string& path, const string&
cuefile_type);
---
> void do_export_cd_markers (const string& path, const string&
cuefile_type);
> void initSpec(ARDOUR::AudioExportSpecification &spec);
115a117,118
> void process_audioranges_export(ARDOUR::Locations::LocationList&
locations, ARDOUR::AudioExportSpecification& spec);
>
131c134
< #endif // __ardour_export_dialog_h__
---
> #endif // __ardour_session_export_dialog_h__
Greetings
Andre
More information about the Ardour-Dev
mailing list