diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/SConscript | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour.menus | 10 | ||||
-rw-r--r-- | gtk2_ardour/crossfade_edit.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/editing.h | 19 | ||||
-rw-r--r-- | gtk2_ardour/editing_syms.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 26 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 24 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 14 | ||||
-rw-r--r-- | gtk2_ardour/editor_audio_import.cc | 395 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 491 | ||||
-rw-r--r-- | gtk2_ardour/editor_region_list.cc | 5 | ||||
-rw-r--r-- | gtk2_ardour/redirect_box.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.cc | 8 | ||||
-rw-r--r-- | gtk2_ardour/sfdb_ui.cc | 138 | ||||
-rw-r--r-- | gtk2_ardour/sfdb_ui.h | 30 | ||||
-rw-r--r-- | gtk2_ardour/utils.cc | 18 | ||||
-rw-r--r-- | gtk2_ardour/utils.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/visual_time_axis.cc | 14 |
20 files changed, 619 insertions, 604 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 09e5b7f7eb..eedc04c3c5 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -93,6 +93,7 @@ default_keys.cc editing.cc editor.cc editor_actions.cc +editor_audio_import.cc editor_audiotrack.cc editor_canvas.cc editor_canvas_events.cc diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 6176032d12..70a8b1d32d 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -11,7 +11,13 @@ <menuitem action='Snapshot'/> <menuitem action='SaveTemplate'/> <separator/> - <menuitem action='AddTrackBus'/> + <menuitem action='AddTrackBus'/> + <separator/> + <menu action='addExistingAudioFiles'> + <menuitem action='addExternalAudioAsRegion'/> + <menuitem action='addExternalAudioAsTrack'/> + <menuitem action='addExternalAudioToTrack'/> + </menu> <separator/> <menu name='Export' action='Export'> <menuitem action='ExportSession'/> @@ -308,6 +314,6 @@ <menuitem action='SortBySourceFilesystem'/> </menu> <separator/> - <menuitem action='addExternalRegion'/> + <menuitem action='addExternalAudioToRegionList'/> </popup> </ui> diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc index 451b9781f5..1b4110be50 100644 --- a/gtk2_ardour/crossfade_edit.cc +++ b/gtk2_ardour/crossfade_edit.cc @@ -212,8 +212,6 @@ CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double m for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) { - cerr << "looking for xpm " << (*i)->xpm << endl; - pxmap = manage (new Image (get_xpm((*i)->xpm))); pbutton = manage (new Button); pbutton->add (*pxmap); diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h index 31da83d984..b25b935ee0 100644 --- a/gtk2_ardour/editing.h +++ b/gtk2_ardour/editing.h @@ -13,6 +13,7 @@ #define MOUSEMODE(a) /*empty*/ #define ZOOMFOCUS(a) /*empty*/ #define DISPLAYCONTROL(a) /*empty*/ +#define IMPORTMODE(a) /*empty*/ namespace Editing { @@ -124,6 +125,24 @@ DisplayControl str2displaycontrol (const std::string &); #undef DISPLAYCONTROL #define DISPLAYCONTROL(a) /*empty*/ +// IMPORTMODE +#undef IMPORTMODE +#define IMPORTMODE(a) a, +enum ImportMode { + #include "editing_syms.h" +}; + +#undef IMPORTMODE +#define IMPORTMODE(s) #s, +static const char *importmodestrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(ImportMode m) {return importmodestrs[m];} +ImportMode str2importmode (const std::string &); + +#undef IMPORTMODE +#define IMPORTMODE(a) /*empty*/ + ///////////////////// // These don't need their state saved. yet... enum CutCopyOp { diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h index b74698c5c4..cf36550fb4 100644 --- a/gtk2_ardour/editing_syms.h +++ b/gtk2_ardour/editing_syms.h @@ -53,3 +53,7 @@ DISPLAYCONTROL(FollowPlayhead) DISPLAYCONTROL(ShowMeasures) DISPLAYCONTROL(ShowWaveforms) DISPLAYCONTROL(ShowWaveformsRecording) + +IMPORTMODE(ImportAsRegion) +IMPORTMODE(ImportAsTrack) +IMPORTMODE(ImportToTrack) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9fe0d2767c..bdb8e841cb 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1982,14 +1982,9 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) /* Adding new material */ - Menu *import_menu = manage (new Menu()); - MenuList& import_items = import_menu->items(); - import_menu->set_name ("ArdourContextMenu"); - - import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f))); - import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false))); - - edit_items.push_back (MenuElem (_("Import"), *import_menu)); + edit_items.push_back (SeparatorElem()); + edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f))); + edit_items.push_back (MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack))); /* Nudge track */ @@ -2905,7 +2900,7 @@ Editor::stop_canvas_autoscroll () } int -Editor::convert_drop_to_paths (vector<string>& paths, +Editor::convert_drop_to_paths (vector<ustring>& paths, const RefPtr<Gdk::DragContext>& context, gint x, gint y, @@ -3445,21 +3440,14 @@ Editor::edit_menu_map_handler (GdkEventAny* ev) import_menu->set_name ("ArdourContextMenu"); MenuList& import_items = import_menu->items(); - import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true))); - import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false))); - - Menu* embed_menu = manage (new Menu()); - embed_menu->set_name ("ArdourContextMenu"); - MenuList& embed_items = embed_menu->items(); - - embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true))); - embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio))); + import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack))); + import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion))); edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu)); - edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu)); edit_items.push_back (SeparatorElem()); edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture))); + if (!session->have_captured()) { edit_items.back().set_sensitive (false); } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index f0fb67694a..dbc76993d9 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -967,18 +967,16 @@ class Editor : public PublicEditor void insert_region_list_drag (ARDOUR::AudioRegion&, int x, int y); void insert_region_list_selection (float times); - void insert_sndfile (bool as_tracks); - void embed_audio (); // inserts into region list - int reject_because_rate_differs (const string & path, ARDOUR::SoundFileInfo& finfo, const string & action, bool multiple_pending); + void add_external_audio_action (Editing::ImportMode); - void do_embed_sndfiles (vector<string> paths, bool split); - void embed_sndfile (string path, bool split, bool multiple_files, bool& check_sr); - - void do_insert_sndfile (vector<string> path, bool multi, jack_nframes_t frame); - void insert_paths_as_new_tracks (std::vector<std::string> paths, bool multi); // inserts files as new tracks - void insert_sndfile_into (const string & path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& frame, bool prompt=true); - static void* _insert_sndfile_thread (void*); - void* insert_sndfile_thread (void*); + void bring_in_external_audio (Editing::ImportMode mode, ARDOUR::AudioTrack*, jack_nframes_t& pos, bool prompt); + void do_import (vector<Glib::ustring> paths, bool split, Editing::ImportMode mode, ARDOUR::AudioTrack*, jack_nframes_t&, bool); + void do_embed (vector<Glib::ustring> paths, bool split, Editing::ImportMode mode, ARDOUR::AudioTrack*, jack_nframes_t&, bool); + void import_sndfile (Glib::ustring path, Editing::ImportMode mode, ARDOUR::AudioTrack* track, jack_nframes_t& pos); + void embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode, + ARDOUR::AudioTrack* track, jack_nframes_t& pos, bool prompt); + int finish_bringing_in_audio (ARDOUR::AudioRegion& region, uint32_t, uint32_t, ARDOUR::AudioTrack* track, jack_nframes_t& pos, Editing::ImportMode mode); + int reject_because_rate_differs (Glib::ustring path, ARDOUR::SoundFileInfo& finfo, const string & action, bool multiple_pending); /* generic interthread progress window */ @@ -1003,8 +1001,6 @@ class Editor : public PublicEditor gint import_progress_timeout (void *); static void *_import_thread (void *); void* import_thread (); - void catch_new_audio_region (ARDOUR::AudioRegion*); - ARDOUR::AudioRegion* last_audio_region; /* to support this ... */ @@ -1586,7 +1582,7 @@ class Editor : public PublicEditor /* Drag-n-Drop */ - int convert_drop_to_paths (std::vector<std::string>& paths, + int convert_drop_to_paths (std::vector<Glib::ustring>& paths, const Glib::RefPtr<Gdk::DragContext>& context, gint x, gint y, diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index d0a5c90144..583c272fe0 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -37,6 +37,7 @@ Editor::register_actions () ActionManager::register_action (editor_actions, X_("Monitoring"), _("Monitoring")); ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect")); ActionManager::register_action (editor_actions, X_("Layering"), _("Layering")); + ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Add Existing Audio")); /* add named actions for the editor */ @@ -339,8 +340,17 @@ Editor::register_actions () bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileCreationDate)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFilesystem"), _("By Source Filesystem"), bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileFS)); - - act = ActionManager::register_action (rl_actions, X_("addExternalAudio"), _("Embed audio (link)"), mem_fun(*this, &Editor::embed_audio)); + + + /* the next two are duplicate items with different names for use in two different contexts */ + + act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Add External Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsRegion"), _("as Region(s)"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsTrack"), _("as Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, X_("addExternalAudioToTrack"), _("to Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformVisibility"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility)); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc new file mode 100644 index 0000000000..658bb6fe74 --- /dev/null +++ b/gtk2_ardour/editor_audio_import.cc @@ -0,0 +1,395 @@ +/* + Copyright (C) 2000-2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <pbd/pthread_utils.h> +#include <pbd/basename.h> + +#include <gtkmm2ext/choice.h> + +#include <ardour/session.h> +#include <ardour/audioplaylist.h> +#include <ardour/audioregion.h> +#include <ardour/diskstream.h> +#include <ardour/filesource.h> +#include <ardour/externalsource.h> +#include <ardour/utils.h> +#include <ardour/audio_track.h> +#include <ardour/audioplaylist.h> + +#include "ardour_ui.h" +#include "editor.h" +#include "sfdb_ui.h" +#include "editing.h" +#include "audio_time_axis.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace sigc; +using namespace Gtk; +using namespace Editing; + +/* Functions supporting the incorporation of external (non-captured) audio material into ardour */ + +void +Editor::add_external_audio_action (ImportMode mode) +{ + jack_nframes_t& pos = edit_cursor->current_frame; + AudioTrack* track = 0; + + if (!selection->tracks.empty()) { + AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front()); + if (atv) { + track = atv->audio_track(); + } + } + + bring_in_external_audio (mode, track, pos, false); +} + +void +Editor::bring_in_external_audio (ImportMode mode, AudioTrack* track, jack_nframes_t& pos, bool prompt) +{ + if (session == 0) { + MessageDialog msg (0, _("You can't import or embed an audiofile until you have a session loaded.")); + msg.run (); + return; + } + + SoundFileOmega sfdb (_("Add existing audio to session")); + sfdb.set_mode (mode); + + switch (sfdb.run()) { + case SoundFileOmega::ResponseImport: + do_import (sfdb.get_paths(), sfdb.get_split(), mode, track, pos, prompt); + break; + + case SoundFileOmega::ResponseEmbed: + do_embed (sfdb.get_paths(), sfdb.get_split(), mode, track, pos, prompt); + break; + + default: + break; + } +} + +void +Editor::do_import (vector<Glib::ustring> paths, bool split, ImportMode mode, AudioTrack* track, jack_nframes_t& pos, bool prompt) +{ + /* SFDB sets "multichan" to true to indicate "split channels" + so reverse the setting to match the way libardour + interprets it. + */ + + import_status.multichan = !split; + + if (interthread_progress_window == 0) { + build_interthread_progress_window (); + } + + /* for each path that was selected, import it and then potentially create a new track + containing the new region as the sole contents. + */ + + for (vector<Glib::ustring>::iterator i = paths.begin(); i != paths.end(); ++i ) { + import_sndfile (*i, mode, track, pos); + } + + interthread_progress_window->hide_all (); +} + +void +Editor::do_embed (vector<Glib::ustring> paths, bool split, ImportMode mode, AudioTrack* track, jack_nframes_t& pos, bool prompt) +{ + bool multiple_files = paths.size() > 1; + bool check_sample_rate = true; + + for (vector<Glib::ustring>::iterator i = paths.begin(); i != paths.end(); ++i) { + embed_sndfile (*i, split, multiple_files, check_sample_rate, mode, track, pos, prompt); + } + + session->save_state (""); +} + +void +Editor::import_sndfile (Glib::ustring path, ImportMode mode, AudioTrack* track, jack_nframes_t& pos) +{ + interthread_progress_window->set_title (string_compose (_("ardour: importing %1"), path)); + interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE); + interthread_progress_window->show_all (); + interthread_progress_bar.set_fraction (0.0f); + interthread_cancel_label.set_text (_("Cancel Import")); + current_interthread_info = &import_status; + + import_status.pathname = path; + import_status.done = false; + import_status.cancel = false; + import_status.freeze = false; + import_status.done = 0.0; + + interthread_progress_connection = Glib::signal_timeout().connect + (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100); + + track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); + ARDOUR_UI::instance()->flush_pending (); + + /* start import thread for this path. this will ultimately call Session::import_audiofile() + and if successful will add the file as a region to the session region list. + */ + + pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this); + pthread_detach (import_status.thread); + + while (!(import_status.done || import_status.cancel)) { + gtk_main_iteration (); + } + + import_status.done = true; + interthread_progress_connection.disconnect (); + + /* import thread finished - see if we should build a new track */ + + if (!import_status.new_regions.empty()) { + AudioRegion& region (*import_status.new_regions.front()); + finish_bringing_in_audio (region, region.n_channels(), region.n_channels(), track, pos, mode); + } + + track_canvas.get_window()->set_cursor (*current_canvas_cursor); +} + +void +Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool& check_sample_rate, ImportMode mode, + AudioTrack* track, jack_nframes_t& pos, bool prompt) +{ + ExternalSource *source = 0; /* keep g++ quiet */ + AudioRegion::SourceList sources; + string idspec; + string linked_path; + SoundFileInfo finfo; + string region_name; + + track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); + ARDOUR_UI::instance()->flush_pending (); + + /* lets see if we can link it into the session */ + + linked_path = session->sound_dir(); + linked_path += PBD::basename (path); + + if (link (path.c_str(), linked_path.c_str()) == 0) { + + /* there are many reasons why link(2) might have failed. + but if it succeeds, we now have a link in the + session sound dir that will protect against + unlinking of the original path. nice. + */ + + path = linked_path; + } + + /* note that we temporarily truncated _id at the colon */ + + string error_msg; + + if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) { + error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg; + return; + } + + if (check_sample_rate) { + switch (reject_because_rate_differs (path, finfo, "Embed", multiple_files)) { + case 0: + break; + case 1: + return; + case -1: + check_sample_rate = false; + break; + + case -2: + default: + return; + } + } + + track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); + ARDOUR_UI::instance()->flush_pending (); + + /* make the proper number of channels in the region */ + + for (int n = 0; n < finfo.channels; ++n) + { + idspec = path; + idspec += string_compose(":%1", n); + + try { + source = ExternalSource::create (idspec.c_str()); + sources.push_back(source); + } + + catch (failed_constructor& err) { + error << string_compose(_("could not open %1"), path) << endmsg; + goto out; + } + + ARDOUR_UI::instance()->flush_pending (); + } + + if (sources.empty()) { + goto out; + } + + region_name = PBD::basename_nosuffix (path); + region_name += "-0"; + + AudioRegion* region = new AudioRegion (sources, 0, sources[0]->length(), region_name, 0, + Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)); + + uint32_t input_chan = finfo.channels; + uint32_t output_chan; + + if (session->get_output_auto_connect() & Session::AutoConnectMaster) { + output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + } else { + output_chan = input_chan; + } + + finish_bringing_in_audio (*region, input_chan, output_chan, track, pos, mode); + + out: + track_canvas.get_window()->set_cursor (*current_canvas_cursor); +} + +int +Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32_t out_chans, AudioTrack* track, jack_nframes_t& pos, ImportMode mode) +{ + switch (mode) { + case ImportAsRegion: + /* relax, its been done */ + break; + + case ImportToTrack: + if (track) { + Playlist* playlist = track->disk_stream().playlist(); + + AudioRegion* copy = new AudioRegion (region); + begin_reversible_command (_("insert sndfile")); + session->add_undo (playlist->get_memento()); + playlist->add_region (*copy, pos); + session->add_redo_no_execute (playlist->get_memento()); + commit_reversible_command (); + + pos += region.length(); + } + break; + + case ImportAsTrack: + AudioTrack* at = session->new_audio_track (in_chans, out_chans); + AudioRegion* copy = new AudioRegion (region); + at->disk_stream().playlist()->add_region (*copy, pos); + break; + } + + return 0; +} + +int +Editor::reject_because_rate_differs (Glib::ustring path, SoundFileInfo& finfo, const string & action, bool multiple_pending) +{ + if (!session) { + return 1; + } + + if (finfo.samplerate != (int) session->frame_rate()) { + vector<string> choices; + + choices.push_back (string_compose (_("%1 it anyway"), action)); + + if (multiple_pending) { + /* XXX assumptions about sentence structure + here for translators. Sorry. + */ + choices.push_back (string_compose (_("Don't %1 it"), action)); + choices.push_back (string_compose (_("%1 all without questions"), action)); + choices.push_back (_("Cancel entire import")); + } else { + choices.push_back (_("Cancel")); + } + + Gtkmm2ext::Choice rate_choice ( + string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path), + choices, false); + + switch (rate_choice.run()) { + case 0: /* do it anyway */ + return 0; + case 1: /* don't import this one */ + return 1; + case 2: /* do the rest without asking */ + return -1; + case 3: /* stop a multi-file import */ + default: + return -2; + } + } + + return 0; +} + +void * +Editor::_import_thread (void *arg) +{ + PBD::ThreadCreated (pthread_self(), X_("Import")); + + Editor *ed = (Editor *) arg; + return ed->import_thread (); +} + +void * +Editor::import_thread () +{ + session->import_audiofile (import_status); + pthread_exit_pbd (0); + /*NOTREACHED*/ + return 0; +} + +gint +Editor::import_progress_timeout (void *arg) +{ + interthread_progress_label.set_text (import_status.doing_what); + + if (import_status.freeze) { + interthread_cancel_button.set_sensitive(false); + } else { + interthread_cancel_button.set_sensitive(true); + } + + if (import_status.doing_what == "building peak files") { + interthread_progress_bar.pulse (); + return FALSE; + } else { + interthread_progress_bar.set_fraction (import_status.progress); + } + + return !(import_status.done || import_status.cancel); +} + diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index c18bf867cd..92844124bd 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -455,7 +455,7 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context, TimeAxisView* tvp; AudioTimeAxisView* tv; double cy; - vector<string> paths; + vector<ustring> paths; string spath; GdkEvent ev; jack_nframes_t frame; @@ -484,22 +484,18 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context, if ((tvp = trackview_by_y_position (cy)) == 0) { - /* drop onto canvas background: create a new track */ - - insert_paths_as_new_tracks (paths, false); + /* drop onto canvas background: create new tracks */ + jack_nframes_t pos = 0; + do_embed (paths, false, ImportAsTrack, 0, pos, false); } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) { /* check that its an audio track, not a bus */ - + if (tv->get_diskstream()) { - - for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) { - insert_sndfile_into (*p, true, tv, frame); - } + do_embed (paths, false, ImportToTrack, tv->audio_track(), frame, true); } - } out: diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 6b38b904e1..4569b39182 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -333,6 +333,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp break; case StreamItem: + set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true); break; case AutomationTrackItem: diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index f5baecb373..ba40d63fe7 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -198,12 +198,8 @@ Do you really want to destroy %1 ?"), choices.push_back (_("No, do nothing.")); Gtkmm2ext::Choice prompter (prompt, choices); - - if (prompter.run () != RESPONSE_ACCEPT) { - return; - } - - if (prompter.get_choice() != 0) { + + if (prompter.run() != 0) { /* first choice */ return; } @@ -1972,483 +1968,6 @@ Editor::interthread_cancel_clicked () } } -void * -Editor::_import_thread (void *arg) -{ - PBD::ThreadCreated (pthread_self(), X_("Import")); - - Editor *ed = (Editor *) arg; - return ed->import_thread (); -} - -void * -Editor::import_thread () -{ - session->import_audiofile (import_status); - return 0; -} - -gint -Editor::import_progress_timeout (void *arg) -{ - interthread_progress_label.set_text (import_status.doing_what); - - if (import_status.freeze) { - interthread_cancel_button.set_sensitive(false); - } else { - interthread_cancel_button.set_sensitive(true); - } - - if (import_status.doing_what == "building peak files") { - interthread_progress_bar.pulse (); - return FALSE; - } else { - interthread_progress_bar.set_fraction (import_status.progress/100); - } - - return !(import_status.done || import_status.cancel); -} - -void -Editor::import_audio (bool as_tracks) -{ - if (session == 0) { - warning << _("You can't import an audiofile until you have a session loaded.") << endmsg; - return; - } - - string str; - - if (as_tracks) { - str =_("Import selected as tracks"); - } else { - str = _("Import selected to region list"); - } - - SoundFileOmega sfdb (str); - sfdb.Imported.connect (bind (mem_fun (*this, &Editor::do_import), as_tracks)); - - sfdb.run(); -} - -void -Editor::catch_new_audio_region (AudioRegion* ar) -{ - last_audio_region = ar; -} - -void -Editor::do_import (vector<string> paths, bool split, bool as_tracks) -{ - sigc::connection c; - - /* SFDB sets "multichan" to true to indicate "split channels" - so reverse the setting to match the way libardour - interprets it. - */ - - import_status.multichan = !split; - - if (interthread_progress_window == 0) { - build_interthread_progress_window (); - } - - interthread_progress_window->set_title (_("ardour: audio import in progress")); - interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE); - interthread_progress_window->show_all (); - interthread_progress_bar.set_fraction (0.0f); - interthread_cancel_label.set_text (_("Cancel Import")); - current_interthread_info = &import_status; - - c = session->AudioRegionAdded.connect (mem_fun(*this, &Editor::catch_new_audio_region)); - - for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i ) { - - interthread_progress_window->set_title (string_compose (_("ardour: importing %1"), (*i))); - - import_status.pathname = (*i); - import_status.done = false; - import_status.cancel = false; - import_status.freeze = false; - import_status.done = 0.0; - - interthread_progress_connection = - Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100); - - last_audio_region = 0; - - pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this); - pthread_detach (import_status.thread); - - while (!(import_status.done || import_status.cancel)) { - gtk_main_iteration (); - } - - import_status.done = true; - interthread_progress_connection.disconnect (); - - if (as_tracks && last_audio_region != 0) { - uint32_t channels = last_audio_region->n_channels(); - - AudioTrack* at = session->new_audio_track (channels, channels); - AudioRegion* copy = new AudioRegion (*last_audio_region); - at->disk_stream().playlist()->add_region (*copy, 0); - } - } - - c.disconnect (); - interthread_progress_window->hide_all (); -} - -int -Editor::reject_because_rate_differs (const string & path, SoundFileInfo& finfo, const string & action, bool multiple_pending) -{ - if (!session) { - return 1; - } - - if (finfo.samplerate != (int) session->frame_rate()) { - vector<string> choices; - - choices.push_back (string_compose (_("%1 it anyway"), action)); - - if (multiple_pending) { - /* XXX assumptions about sentence structure - here for translators. Sorry. - */ - choices.push_back (string_compose (_("Don't %1 it"), action)); - choices.push_back (string_compose (_("%1 all without questions"), action)); - choices.push_back (_("Cancel entire import")); - } else { - choices.push_back (_("Cancel")); - } - - Gtkmm2ext::Choice rate_choice ( - string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path), - choices); - - int response = rate_choice.run(); - - switch (response) { - case RESPONSE_ACCEPT: - break; - default: - /* stop all that might come after this */ - return -2; - break; - } - - switch (rate_choice.get_choice()) { - case 0: /* do it anyway */ - return 0; - case 1: /* don't import this one */ - return 1; - case 2: /* do the rest without asking */ - return -1; - case 3: /* stop a multi-file import */ - default: - return -2; - } - } - - return 0; -} - -void -Editor::embed_audio () -{ - if (session == 0) { - warning << _("You can't embed an audiofile until you have a session loaded.") << endmsg; - return; - } - - SoundFileOmega sfdb (_("Add to External Region list")); - sfdb.Embedded.connect (mem_fun (*this, &Editor::do_embed_sndfiles)); - - sfdb.run (); -} - -void -Editor::do_embed_sndfiles (vector<string> paths, bool split) -{ - bool multiple_files = paths.size() > 1; - bool check_sample_rate = true; - - for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i) { - embed_sndfile (*i, split, multiple_files, check_sample_rate); - } - - session->save_state (""); -} - -void -Editor::embed_sndfile (string path, bool split, bool multiple_files, bool& check_sample_rate) -{ - ExternalSource *source = 0; /* keep g++ quiet */ - AudioRegion::SourceList sources; - string idspec; - string linked_path; - SoundFileInfo finfo; - - /* lets see if we can link it into the session */ - - linked_path = session->sound_dir(); - linked_path += PBD::basename (path); - - if (link (path.c_str(), linked_path.c_str()) == 0) { - - /* there are many reasons why link(2) might have failed. - but if it succeeds, we now have a link in the - session sound dir that will protect against - unlinking of the original path. nice. - */ - - path = linked_path; - } - - /* note that we temporarily truncated _id at the colon */ - string error_msg; - if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) { - error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg; - return; - } - - if (check_sample_rate) { - switch (reject_because_rate_differs (path, finfo, "Embed", multiple_files)) { - case 0: - break; - case 1: - return; - case -1: - check_sample_rate = false; - break; - - case -2: - default: - return; - } - } - - track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); - ARDOUR_UI::instance()->flush_pending (); - - /* make the proper number of channels in the region */ - - for (int n=0; n < finfo.channels; ++n) - { - idspec = path; - idspec += string_compose(":%1", n); - - try { - source = ExternalSource::create (idspec.c_str()); - sources.push_back(source); - } - - catch (failed_constructor& err) { - error << string_compose(_("could not open %1"), path) << endmsg; - goto out; - } - - ARDOUR_UI::instance()->flush_pending (); - } - - if (sources.size() > 0) { - - string region_name = PBD::basename_nosuffix (path); - region_name += "-0"; - - /* The created region isn't dropped. It emits a signal - that is picked up by the session. - */ - - new AudioRegion (sources, 0, sources[0]->length(), region_name, 0, - Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)); - - /* make sure we can see it in the list */ - - /* its the second node, always */ - - // GTK2FIX ?? is it still always the 2nd node - - TreeModel::Path path ("2"); - region_list_display.expand_row (path, true); - - ARDOUR_UI::instance()->flush_pending (); - } - - out: - track_canvas.get_window()->set_cursor (*current_canvas_cursor); -} - -void -Editor::insert_sndfile (bool as_tracks) -{ -// SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); - sigc::connection c; - string str; - - if (as_tracks) { - -// c = sfdb.Action.connect (mem_fun(*this, &Editor::insert_paths_as_new_tracks)); - str = _("Insert selected as new tracks"); - - } else { - - jack_nframes_t pos; - - if (clicked_audio_trackview == 0) { - return; - } - - if (ensure_cursor (&pos)) { - return; - } - -// c = sfdb.Action.connect (bind (mem_fun(*this, &Editor::do_insert_sndfile), pos)); - str = _("Insert selected"); - } - -// sfdb.run (str, false); -// c.disconnect (); -} - -void -Editor::insert_paths_as_new_tracks (vector<string> paths, bool split) -{ - SoundFileInfo finfo; - bool multiple_files; - bool check_sample_rate = true; - string error_msg; - - multiple_files = paths.size() > 1; - - for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) { - - if (!ExternalSource::get_soundfile_info((*p), finfo, error_msg)) { - error << string_compose(_("Editor: cannot open file \"%1\" (%2)"), (*p), error_msg) << endmsg; - continue; - } - - /* add a new track */ - - if (check_sample_rate) { - switch (reject_because_rate_differs (*p, finfo, "Insert", multiple_files)) { - case 0: - break; - case 1: - continue; - case -1: - check_sample_rate = false; - break; - - case -2: - return; - } - } - - uint32_t input_chan = finfo.channels; - uint32_t output_chan; - - if (session->get_output_auto_connect() & Session::AutoConnectMaster) { - output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); - } else { - output_chan = input_chan; - } - - (void) session->new_audio_track (input_chan, output_chan); - - - /* get the last (most recently added) track view */ - - AudioTimeAxisView* tv; - - if ((tv = dynamic_cast<AudioTimeAxisView*>(track_views.back())) == 0) { - fatal << _("programming error: ") - << X_("last trackview after new_audio_track is not an audio track!") - << endmsg; - /*NOTREACHED*/ - } - - jack_nframes_t pos = 0; - insert_sndfile_into (*p, true, tv, pos, false); - } -} - -void -Editor::do_insert_sndfile (vector<string> paths, bool split, jack_nframes_t pos) -{ - for (vector<string>::iterator x = paths.begin(); x != paths.end(); ++x) { - insert_sndfile_into (*x, !split, clicked_audio_trackview, pos); - } -} - -void -Editor::insert_sndfile_into (const string & path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& pos, bool prompt) -{ - ExternalSource *source = 0; /* keep g++ quiet */ - AudioRegion::SourceList sources; - string idspec; - SoundFileInfo finfo; - string error_msg; - - /* note that we temporarily truncated _id at the colon */ - - if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) { - error << string_compose(_("Editor: cannot open file \"%1\" (%2)"), path, error_msg) << endmsg; - return; - } - - if (prompt && (reject_because_rate_differs (path, finfo, "Insert", false) != 0)) { - return; - } - - track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); - ARDOUR_UI::instance()->flush_pending (); - - /* make the proper number of channels in the region */ - - for (int n=0; n < finfo.channels; ++n) - { - idspec = path; - idspec += string_compose(":%1", n); - - try { - source = ExternalSource::create (idspec.c_str()); - sources.push_back(source); - } - - catch (failed_constructor& err) { - error << string_compose(_("could not open %1"), path) << endmsg; - goto out; - } - - ARDOUR_UI::instance()->flush_pending (); - } - - if (sources.size() > 0) { - - string region_name = region_name_from_path (PBD::basename (path)); - - AudioRegion *region = new AudioRegion (sources, 0, sources[0]->length(), region_name, - 0, /* irrelevant these days */ - Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)); - - begin_reversible_command (_("insert sndfile")); - session->add_undo (tv->playlist()->get_memento()); - tv->playlist()->add_region (*region, pos); - session->add_redo_no_execute (tv->playlist()->get_memento()); - commit_reversible_command (); - - pos += sources[0]->length(); - - ARDOUR_UI::instance()->flush_pending (); - } - - out: - track_canvas.get_window()->set_cursor (*current_canvas_cursor); - return; -} - void Editor::region_from_selection () { @@ -3552,10 +3071,8 @@ Editor::remove_last_capture () Gtkmm2ext::Choice prompter (prompt, choices); - if (prompter.run () == RESPONSE_ACCEPT) { - if (prompter.get_choice() == 0) { - session->remove_last_capture (); - } + if (prompter.run () == 0) { + session->remove_last_capture (); } } else { diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc index 464a707512..4506b69b5e 100644 --- a/gtk2_ardour/editor_region_list.cc +++ b/gtk2_ardour/editor_region_list.cc @@ -574,10 +574,11 @@ Editor::region_list_display_drag_data_received (const RefPtr<Gdk::DragContext>& const SelectionData& data, guint info, guint time) { - vector<string> paths; + vector<ustring> paths; if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { - do_embed_sndfiles (paths, false); + jack_nframes_t pos = 0; + do_embed (paths, false, ImportAsRegion, 0, pos, true); context->drag_finish (true, false, time); } } diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index e95596fbf9..a9cb78d5c4 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -900,10 +900,8 @@ RedirectBox::clear_redirects() Gtkmm2ext::Choice prompter (prompt, choices); - if (prompter.run () == RESPONSE_ACCEPT) { - if (prompter.get_choice() == 0) { - _route.clear_redirects (this); - } + if (prompter.run () == 0) { + _route.clear_redirects (this); } } diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index bf286e36f0..a96ca82009 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -703,12 +703,8 @@ RouteUI::remove_this_route () Choice prompter (prompt, choices); - prompter.show_all (); - - if (prompter.run () == RESPONSE_ACCEPT) { - if (prompter.get_choice() == 0) { - Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this)); - } + if (prompter.run () == 0) { + Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this)); } } diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index 3c8f258f4a..69c8200dd5 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -22,11 +22,13 @@ #include <map> #include <cerrno> -#include <pbd/basename.h> - #include <gtkmm/box.h> #include <gtkmm/stock.h> +#include <pbd/basename.h> + +#include <gtkmm2ext/utils.h> + #include <ardour/audio_library.h> #include <ardour/audioregion.h> #include <ardour/externalsource.h> @@ -34,12 +36,14 @@ #include "gui_thread.h" #include "prompter.h" #include "sfdb_ui.h" +#include "utils.h" #include "i18n.h" using namespace ARDOUR; +using namespace std; -std::string length2string (const int32_t frames, const float sample_rate); +string length2string (const int32_t frames, const float sample_rate); SoundFileBox::SoundFileBox () : @@ -264,8 +268,8 @@ SoundFileBox::delete_row (const Gtk::TreeModel::iterator& iter) void SoundFileBox::audition_status_changed (bool active) { - ENSURE_GUI_THREAD(bind (mem_fun (*this, &SoundFileBox::audition_status_changed), active)); - + ENSURE_GUI_THREAD(bind (mem_fun (*this, &SoundFileBox::audition_status_changed), active)); + if (!active) { stop_btn_clicked (); } @@ -281,13 +285,13 @@ SoundFileBox::field_selected () } } -SoundFileBrowser::SoundFileBrowser (std::string title) - : - ArdourDialog(title), - chooser(Gtk::FILE_CHOOSER_ACTION_OPEN) +SoundFileBrowser::SoundFileBrowser (string title) + : ArdourDialog (title, false), + chooser (Gtk::FILE_CHOOSER_ACTION_OPEN) { get_vbox()->pack_start(chooser); chooser.set_preview_widget(preview); + chooser.set_select_multiple (true); chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview)); } @@ -304,63 +308,117 @@ SoundFileBrowser::update_preview () chooser.set_preview_widget_active(preview.setup_labels(chooser.get_filename())); } -SoundFileChooser::SoundFileChooser (std::string title) +SoundFileChooser::SoundFileChooser (string title) : SoundFileBrowser(title) { add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK); add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - show_all (); } -SoundFileOmega::SoundFileOmega (std::string title) - : - SoundFileBrowser(title), - embed_btn (_("Embed")), - import_btn (_("Import")), - split_check (_("Split Channels")) +static const char *import_mode_strings[] = { + X_("Add to Region list"), + X_("Add as new Track(s)"), + X_("Add to selected Track(s)"), + 0 +}; + +vector<string> SoundFileOmega::mode_strings; + +SoundFileOmega::SoundFileOmega (string title) + : SoundFileBrowser (title), + split_check (_("Split Channels")) { - get_action_area()->pack_start(embed_btn); - get_action_area()->pack_start(import_btn); + if (mode_strings.empty()) { + mode_strings = internationalize (import_mode_strings); + } + + add_button (_("Embed"), ResponseEmbed); + add_button (_("Import"), ResponseImport); add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE); - chooser.set_extra_widget(split_check); + Gtk::HBox *box = manage (new Gtk::HBox()); + + Gtkmm2ext::set_popdown_strings (mode_combo, mode_strings); + + set_mode (Editing::ImportAsRegion); - embed_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::embed_clicked)); - import_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::import_clicked)); + box->pack_start (split_check); + box->pack_start (mode_combo); + mode_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::mode_changed)); + + chooser.set_extra_widget (*box); + show_all (); } -void -SoundFileOmega::embed_clicked () +bool +SoundFileOmega::get_split () +{ + return split_check.get_active(); +} + +vector<Glib::ustring> +SoundFileOmega::get_paths () { - Embedded (chooser.get_filenames(), split_check.get_active()); + return chooser.get_filenames(); } void -SoundFileOmega::import_clicked () +SoundFileOmega::set_mode (Editing::ImportMode mode) { - Imported (chooser.get_filenames(), split_check.get_active()); + mode_combo.set_active_text (mode_strings[(int)mode]); + + switch (mode) { + case Editing::ImportAsRegion: + split_check.set_sensitive (true); + break; + case Editing::ImportAsTrack: + split_check.set_sensitive (true); + break; + case Editing::ImportToTrack: + split_check.set_sensitive (false); + break; + } } -std::string -length2string (const int32_t frames, const float sample_rate) +Editing::ImportMode +SoundFileOmega::get_mode () { - int secs = (int) (frames / sample_rate); - int hrs = secs / 3600; - secs -= (hrs * 3600); - int mins = secs / 60; - secs -= (mins * 60); + vector<string>::iterator i; + uint32_t n; + string str = mode_combo.get_active_text (); - int total_secs = (hrs * 3600) + (mins * 60) + secs; - int frames_remaining = frames - (total_secs * sample_rate); - float fractional_secs = (float) frames_remaining / sample_rate; + for (n = 0, i = mode_strings.begin (); i != mode_strings.end(); ++i, ++n) { + if (str == (*i)) { + break; + } + } - char duration_str[32]; - sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs); + if (i == mode_strings.end()) { + fatal << string_compose (_("programming error: %1"), X_("unknown import mode string")) << endmsg; + /*NOTREACHED*/ + } - return duration_str; + return (Editing::ImportMode) (n); } +void +SoundFileOmega::mode_changed () +{ + Editing::ImportMode mode = get_mode(); + + switch (mode) { + case Editing::ImportAsRegion: + split_check.set_sensitive (true); + break; + case Editing::ImportAsTrack: + split_check.set_sensitive (true); + break; + case Editing::ImportToTrack: + split_check.set_sensitive (false); + break; + } +} diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index 10a5e9e0fc..9d730bc3cd 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -33,6 +33,7 @@ #include <gtkmm/dialog.h> #include <gtkmm/entry.h> #include <gtkmm/filechooserwidget.h> +#include <gtkmm/comboboxtext.h> #include <gtkmm/frame.h> #include <gtkmm/label.h> #include <gtkmm/liststore.h> @@ -42,6 +43,7 @@ #include <ardour/externalsource.h> #include "ardour_dialog.h" +#include "editing.h" class SoundFileBox : public Gtk::VBox { @@ -110,7 +112,8 @@ class SoundFileBrowser : public ArdourDialog SoundFileBrowser (std::string title); virtual ~SoundFileBrowser () {}; - virtual void set_session (ARDOUR::Session*); + virtual void set_session (ARDOUR::Session*); + protected: Gtk::FileChooserWidget chooser; SoundFileBox preview; @@ -133,16 +136,27 @@ class SoundFileOmega : public SoundFileBrowser SoundFileOmega (std::string title); virtual ~SoundFileOmega () {}; - sigc::signal<void, std::vector<std::string>, bool> Embedded; - sigc::signal<void, std::vector<std::string>, bool> Imported; + /* these are returned by the Dialog::run() method. note + that builtin GTK responses are all negative, leaving + positive values for application-defined responses. + */ + + const static int ResponseImport = 1; + const static int ResponseEmbed = 2; + + std::vector<Glib::ustring> get_paths (); + bool get_split (); + + void set_mode (Editing::ImportMode); + Editing::ImportMode get_mode (); protected: - Gtk::Button embed_btn; - Gtk::Button import_btn; - Gtk::CheckButton split_check; + Gtk::CheckButton split_check; + Gtk::ComboBoxText mode_combo; + + void mode_changed (); - void embed_clicked (); - void import_clicked (); + static std::vector<std::string> mode_strings; }; #endif // __ardour_sfdb_ui_h__ diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index c0f1a9eaa8..c96f9a3da1 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -592,3 +592,21 @@ get_xpm (std::string name) return (xpm_map[name]); } +string +length2string (const int32_t frames, const float sample_rate) +{ + int secs = (int) (frames / sample_rate); + int hrs = secs / 3600; + secs -= (hrs * 3600); + int mins = secs / 60; + secs -= (mins * 60); + + int total_secs = (hrs * 3600) + (mins * 60) + secs; + int frames_remaining = frames - (total_secs * sample_rate); + float fractional_secs = (float) frames_remaining / sample_rate; + + char duration_str[32]; + sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs); + + return duration_str; +} diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h index 983753a0dd..608ba10529 100644 --- a/gtk2_ardour/utils.h +++ b/gtk2_ardour/utils.h @@ -80,5 +80,6 @@ bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev); Glib::RefPtr<Gdk::Pixbuf> get_xpm(std::string); static std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > xpm_map; const char* const *get_xpm_data (std::string path); +std::string length2string (const int32_t frames, const float sample_rate); #endif /* __ardour_gtk_utils_h__ */ diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc index 23af21aaca..582c18c86f 100644 --- a/gtk2_ardour/visual_time_axis.cc +++ b/gtk2_ardour/visual_time_axis.cc @@ -279,14 +279,12 @@ VisualTimeAxis::remove_this_time_axis(void* src) Gtkmm2ext::Choice prompter (prompt, choices); - if (prompter.run () == RESPONSE_ACCEPT) { - if (prompter.get_choice() == 0) { - /* - defer to idle loop, otherwise we'll delete this object - while we're still inside this function ... - */ - Glib::signal_idle().connect(bind(sigc::ptr_fun(&VisualTimeAxis::idle_remove_this_time_axis), this, src)); - } + if (prompter.run () == 0) { + /* + defer to idle loop, otherwise we'll delete this object + while we're still inside this function ... + */ + Glib::signal_idle().connect(bind(sigc::ptr_fun(&VisualTimeAxis::idle_remove_this_time_axis), this, src)); } } |