significant changes in code to handle import/embedding - much cleaner and less code, plus the import progress bar now works; unify response handling for Gtkmm2ext::Choice

git-svn-id: svn://localhost/trunk/ardour2@415 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-03-22 17:03:00 +00:00
parent 004a49b0c7
commit 3aa346b253
25 changed files with 647 additions and 647 deletions

View file

@ -93,6 +93,7 @@ default_keys.cc
editing.cc editing.cc
editor.cc editor.cc
editor_actions.cc editor_actions.cc
editor_audio_import.cc
editor_audiotrack.cc editor_audiotrack.cc
editor_canvas.cc editor_canvas.cc
editor_canvas_events.cc editor_canvas_events.cc

View file

@ -13,6 +13,12 @@
<separator/> <separator/>
<menuitem action='AddTrackBus'/> <menuitem action='AddTrackBus'/>
<separator/> <separator/>
<menu action='addExistingAudioFiles'>
<menuitem action='addExternalAudioAsRegion'/>
<menuitem action='addExternalAudioAsTrack'/>
<menuitem action='addExternalAudioToTrack'/>
</menu>
<separator/>
<menu name='Export' action='Export'> <menu name='Export' action='Export'>
<menuitem action='ExportSession'/> <menuitem action='ExportSession'/>
<menuitem action='ExportSelection'/> <menuitem action='ExportSelection'/>
@ -308,6 +314,6 @@
<menuitem action='SortBySourceFilesystem'/> <menuitem action='SortBySourceFilesystem'/>
</menu> </menu>
<separator/> <separator/>
<menuitem action='addExternalRegion'/> <menuitem action='addExternalAudioToRegionList'/>
</popup> </popup>
</ui> </ui>

View file

@ -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) { 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))); pxmap = manage (new Image (get_xpm((*i)->xpm)));
pbutton = manage (new Button); pbutton = manage (new Button);
pbutton->add (*pxmap); pbutton->add (*pxmap);

View file

@ -13,6 +13,7 @@
#define MOUSEMODE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/
#define ZOOMFOCUS(a) /*empty*/ #define ZOOMFOCUS(a) /*empty*/
#define DISPLAYCONTROL(a) /*empty*/ #define DISPLAYCONTROL(a) /*empty*/
#define IMPORTMODE(a) /*empty*/
namespace Editing { namespace Editing {
@ -124,6 +125,24 @@ DisplayControl str2displaycontrol (const std::string &);
#undef DISPLAYCONTROL #undef DISPLAYCONTROL
#define DISPLAYCONTROL(a) /*empty*/ #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... // These don't need their state saved. yet...
enum CutCopyOp { enum CutCopyOp {

View file

@ -53,3 +53,7 @@ DISPLAYCONTROL(FollowPlayhead)
DISPLAYCONTROL(ShowMeasures) DISPLAYCONTROL(ShowMeasures)
DISPLAYCONTROL(ShowWaveforms) DISPLAYCONTROL(ShowWaveforms)
DISPLAYCONTROL(ShowWaveformsRecording) DISPLAYCONTROL(ShowWaveformsRecording)
IMPORTMODE(ImportAsRegion)
IMPORTMODE(ImportAsTrack)
IMPORTMODE(ImportToTrack)

View file

@ -1982,14 +1982,9 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
/* Adding new material */ /* Adding new material */
Menu *import_menu = manage (new Menu()); edit_items.push_back (SeparatorElem());
MenuList& import_items = import_menu->items(); edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
import_menu->set_name ("ArdourContextMenu"); edit_items.push_back (MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
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));
/* Nudge track */ /* Nudge track */
@ -2905,7 +2900,7 @@ Editor::stop_canvas_autoscroll ()
} }
int int
Editor::convert_drop_to_paths (vector<string>& paths, Editor::convert_drop_to_paths (vector<ustring>& paths,
const RefPtr<Gdk::DragContext>& context, const RefPtr<Gdk::DragContext>& context,
gint x, gint x,
gint y, gint y,
@ -3445,21 +3440,14 @@ Editor::edit_menu_map_handler (GdkEventAny* ev)
import_menu->set_name ("ArdourContextMenu"); import_menu->set_name ("ArdourContextMenu");
MenuList& import_items = import_menu->items(); 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 track"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack)));
import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false))); import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion)));
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)));
edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu)); 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 (SeparatorElem());
edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture))); edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
if (!session->have_captured()) { if (!session->have_captured()) {
edit_items.back().set_sensitive (false); edit_items.back().set_sensitive (false);
} }

View file

@ -967,18 +967,16 @@ class Editor : public PublicEditor
void insert_region_list_drag (ARDOUR::AudioRegion&, int x, int y); void insert_region_list_drag (ARDOUR::AudioRegion&, int x, int y);
void insert_region_list_selection (float times); void insert_region_list_selection (float times);
void insert_sndfile (bool as_tracks); void add_external_audio_action (Editing::ImportMode);
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 do_embed_sndfiles (vector<string> paths, bool split); void bring_in_external_audio (Editing::ImportMode mode, ARDOUR::AudioTrack*, jack_nframes_t& pos, bool prompt);
void embed_sndfile (string path, bool split, bool multiple_files, bool& check_sr); 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 do_insert_sndfile (vector<string> path, bool multi, jack_nframes_t frame); void import_sndfile (Glib::ustring path, Editing::ImportMode mode, ARDOUR::AudioTrack* track, jack_nframes_t& pos);
void insert_paths_as_new_tracks (std::vector<std::string> paths, bool multi); // inserts files as new tracks void embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode,
void insert_sndfile_into (const string & path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& frame, bool prompt=true); ARDOUR::AudioTrack* track, jack_nframes_t& pos, bool prompt);
static void* _insert_sndfile_thread (void*); int finish_bringing_in_audio (ARDOUR::AudioRegion& region, uint32_t, uint32_t, ARDOUR::AudioTrack* track, jack_nframes_t& pos, Editing::ImportMode mode);
void* insert_sndfile_thread (void*); int reject_because_rate_differs (Glib::ustring path, ARDOUR::SoundFileInfo& finfo, const string & action, bool multiple_pending);
/* generic interthread progress window */ /* generic interthread progress window */
@ -1003,8 +1001,6 @@ class Editor : public PublicEditor
gint import_progress_timeout (void *); gint import_progress_timeout (void *);
static void *_import_thread (void *); static void *_import_thread (void *);
void* import_thread (); void* import_thread ();
void catch_new_audio_region (ARDOUR::AudioRegion*);
ARDOUR::AudioRegion* last_audio_region;
/* to support this ... */ /* to support this ... */
@ -1586,7 +1582,7 @@ class Editor : public PublicEditor
/* Drag-n-Drop */ /* 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, const Glib::RefPtr<Gdk::DragContext>& context,
gint x, gint x,
gint y, gint y,

View file

@ -37,6 +37,7 @@ Editor::register_actions ()
ActionManager::register_action (editor_actions, X_("Monitoring"), _("Monitoring")); ActionManager::register_action (editor_actions, X_("Monitoring"), _("Monitoring"));
ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect")); ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect"));
ActionManager::register_action (editor_actions, X_("Layering"), _("Layering")); ActionManager::register_action (editor_actions, X_("Layering"), _("Layering"));
ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Add Existing Audio"));
/* add named actions for the editor */ /* add named actions for the editor */
@ -340,7 +341,16 @@ Editor::register_actions ()
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFilesystem"), _("By Source Filesystem"), 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)); 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::session_sensitive_actions.push_back (act);
ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformVisibility"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility)); ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformVisibility"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility));

View file

@ -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);
}

View file

@ -455,7 +455,7 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
TimeAxisView* tvp; TimeAxisView* tvp;
AudioTimeAxisView* tv; AudioTimeAxisView* tv;
double cy; double cy;
vector<string> paths; vector<ustring> paths;
string spath; string spath;
GdkEvent ev; GdkEvent ev;
jack_nframes_t frame; jack_nframes_t frame;
@ -484,22 +484,18 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
if ((tvp = trackview_by_y_position (cy)) == 0) { if ((tvp = trackview_by_y_position (cy)) == 0) {
/* drop onto canvas background: create a new track */ /* drop onto canvas background: create new tracks */
insert_paths_as_new_tracks (paths, false);
jack_nframes_t pos = 0;
do_embed (paths, false, ImportAsTrack, 0, pos, false);
} else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) { } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
/* check that its an audio track, not a bus */ /* check that its an audio track, not a bus */
if (tv->get_diskstream()) { if (tv->get_diskstream()) {
do_embed (paths, false, ImportToTrack, tv->audio_track(), frame, true);
for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
insert_sndfile_into (*p, true, tv, frame);
}
} }
} }
out: out:

View file

@ -333,6 +333,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
break; break;
case StreamItem: case StreamItem:
set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true);
break; break;
case AutomationTrackItem: case AutomationTrackItem:

View file

@ -199,11 +199,7 @@ Do you really want to destroy %1 ?"),
Gtkmm2ext::Choice prompter (prompt, choices); Gtkmm2ext::Choice prompter (prompt, choices);
if (prompter.run () != RESPONSE_ACCEPT) { if (prompter.run() != 0) { /* first choice */
return;
}
if (prompter.get_choice() != 0) {
return; 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 void
Editor::region_from_selection () Editor::region_from_selection ()
{ {
@ -3552,10 +3071,8 @@ Editor::remove_last_capture ()
Gtkmm2ext::Choice prompter (prompt, choices); Gtkmm2ext::Choice prompter (prompt, choices);
if (prompter.run () == RESPONSE_ACCEPT) { if (prompter.run () == 0) {
if (prompter.get_choice() == 0) { session->remove_last_capture ();
session->remove_last_capture ();
}
} }
} else { } else {

View file

@ -574,10 +574,11 @@ Editor::region_list_display_drag_data_received (const RefPtr<Gdk::DragContext>&
const SelectionData& data, const SelectionData& data,
guint info, guint time) guint info, guint time)
{ {
vector<string> paths; vector<ustring> paths;
if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { 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); context->drag_finish (true, false, time);
} }
} }

View file

@ -900,10 +900,8 @@ RedirectBox::clear_redirects()
Gtkmm2ext::Choice prompter (prompt, choices); Gtkmm2ext::Choice prompter (prompt, choices);
if (prompter.run () == RESPONSE_ACCEPT) { if (prompter.run () == 0) {
if (prompter.get_choice() == 0) { _route.clear_redirects (this);
_route.clear_redirects (this);
}
} }
} }

View file

@ -703,12 +703,8 @@ RouteUI::remove_this_route ()
Choice prompter (prompt, choices); Choice prompter (prompt, choices);
prompter.show_all (); if (prompter.run () == 0) {
Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
if (prompter.run () == RESPONSE_ACCEPT) {
if (prompter.get_choice() == 0) {
Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
}
} }
} }

View file

@ -22,11 +22,13 @@
#include <map> #include <map>
#include <cerrno> #include <cerrno>
#include <pbd/basename.h>
#include <gtkmm/box.h> #include <gtkmm/box.h>
#include <gtkmm/stock.h> #include <gtkmm/stock.h>
#include <pbd/basename.h>
#include <gtkmm2ext/utils.h>
#include <ardour/audio_library.h> #include <ardour/audio_library.h>
#include <ardour/audioregion.h> #include <ardour/audioregion.h>
#include <ardour/externalsource.h> #include <ardour/externalsource.h>
@ -34,12 +36,14 @@
#include "gui_thread.h" #include "gui_thread.h"
#include "prompter.h" #include "prompter.h"
#include "sfdb_ui.h" #include "sfdb_ui.h"
#include "utils.h"
#include "i18n.h" #include "i18n.h"
using namespace ARDOUR; 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 () SoundFileBox::SoundFileBox ()
: :
@ -264,7 +268,7 @@ SoundFileBox::delete_row (const Gtk::TreeModel::iterator& iter)
void void
SoundFileBox::audition_status_changed (bool active) 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) { if (!active) {
stop_btn_clicked (); stop_btn_clicked ();
@ -281,13 +285,13 @@ SoundFileBox::field_selected ()
} }
} }
SoundFileBrowser::SoundFileBrowser (std::string title) SoundFileBrowser::SoundFileBrowser (string title)
: : ArdourDialog (title, false),
ArdourDialog(title), chooser (Gtk::FILE_CHOOSER_ACTION_OPEN)
chooser(Gtk::FILE_CHOOSER_ACTION_OPEN)
{ {
get_vbox()->pack_start(chooser); get_vbox()->pack_start(chooser);
chooser.set_preview_widget(preview); chooser.set_preview_widget(preview);
chooser.set_select_multiple (true);
chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview)); 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())); chooser.set_preview_widget_active(preview.setup_labels(chooser.get_filename()));
} }
SoundFileChooser::SoundFileChooser (std::string title) SoundFileChooser::SoundFileChooser (string title)
: :
SoundFileBrowser(title) SoundFileBrowser(title)
{ {
add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK); add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
show_all (); show_all ();
} }
SoundFileOmega::SoundFileOmega (std::string title) static const char *import_mode_strings[] = {
: X_("Add to Region list"),
SoundFileBrowser(title), X_("Add as new Track(s)"),
embed_btn (_("Embed")), X_("Add to selected Track(s)"),
import_btn (_("Import")), 0
split_check (_("Split Channels")) };
vector<string> SoundFileOmega::mode_strings;
SoundFileOmega::SoundFileOmega (string title)
: SoundFileBrowser (title),
split_check (_("Split Channels"))
{ {
get_action_area()->pack_start(embed_btn); if (mode_strings.empty()) {
get_action_area()->pack_start(import_btn); mode_strings = internationalize (import_mode_strings);
}
add_button (_("Embed"), ResponseEmbed);
add_button (_("Import"), ResponseImport);
add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE); add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
chooser.set_extra_widget(split_check); Gtk::HBox *box = manage (new Gtk::HBox());
embed_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::embed_clicked)); Gtkmm2ext::set_popdown_strings (mode_combo, mode_strings);
import_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::import_clicked));
set_mode (Editing::ImportAsRegion);
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 (); show_all ();
} }
void bool
SoundFileOmega::embed_clicked () SoundFileOmega::get_split ()
{ {
Embedded (chooser.get_filenames(), split_check.get_active()); return split_check.get_active();
}
vector<Glib::ustring>
SoundFileOmega::get_paths ()
{
return chooser.get_filenames();
} }
void 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 Editing::ImportMode
length2string (const int32_t frames, const float sample_rate) SoundFileOmega::get_mode ()
{ {
int secs = (int) (frames / sample_rate); vector<string>::iterator i;
int hrs = secs / 3600; uint32_t n;
secs -= (hrs * 3600); string str = mode_combo.get_active_text ();
int mins = secs / 60;
secs -= (mins * 60);
int total_secs = (hrs * 3600) + (mins * 60) + secs; for (n = 0, i = mode_strings.begin (); i != mode_strings.end(); ++i, ++n) {
int frames_remaining = frames - (total_secs * sample_rate); if (str == (*i)) {
float fractional_secs = (float) frames_remaining / sample_rate; break;
}
}
char duration_str[32]; if (i == mode_strings.end()) {
sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs); 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;
}
}

View file

@ -33,6 +33,7 @@
#include <gtkmm/dialog.h> #include <gtkmm/dialog.h>
#include <gtkmm/entry.h> #include <gtkmm/entry.h>
#include <gtkmm/filechooserwidget.h> #include <gtkmm/filechooserwidget.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/frame.h> #include <gtkmm/frame.h>
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <gtkmm/liststore.h> #include <gtkmm/liststore.h>
@ -42,6 +43,7 @@
#include <ardour/externalsource.h> #include <ardour/externalsource.h>
#include "ardour_dialog.h" #include "ardour_dialog.h"
#include "editing.h"
class SoundFileBox : public Gtk::VBox class SoundFileBox : public Gtk::VBox
{ {
@ -110,7 +112,8 @@ class SoundFileBrowser : public ArdourDialog
SoundFileBrowser (std::string title); SoundFileBrowser (std::string title);
virtual ~SoundFileBrowser () {}; virtual ~SoundFileBrowser () {};
virtual void set_session (ARDOUR::Session*); virtual void set_session (ARDOUR::Session*);
protected: protected:
Gtk::FileChooserWidget chooser; Gtk::FileChooserWidget chooser;
SoundFileBox preview; SoundFileBox preview;
@ -133,16 +136,27 @@ class SoundFileOmega : public SoundFileBrowser
SoundFileOmega (std::string title); SoundFileOmega (std::string title);
virtual ~SoundFileOmega () {}; virtual ~SoundFileOmega () {};
sigc::signal<void, std::vector<std::string>, bool> Embedded; /* these are returned by the Dialog::run() method. note
sigc::signal<void, std::vector<std::string>, bool> Imported; 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: protected:
Gtk::Button embed_btn; Gtk::CheckButton split_check;
Gtk::Button import_btn; Gtk::ComboBoxText mode_combo;
Gtk::CheckButton split_check;
void embed_clicked (); void mode_changed ();
void import_clicked ();
static std::vector<std::string> mode_strings;
}; };
#endif // __ardour_sfdb_ui_h__ #endif // __ardour_sfdb_ui_h__

View file

@ -592,3 +592,21 @@ get_xpm (std::string name)
return (xpm_map[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;
}

View file

@ -80,5 +80,6 @@ bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev);
Glib::RefPtr<Gdk::Pixbuf> get_xpm(std::string); Glib::RefPtr<Gdk::Pixbuf> get_xpm(std::string);
static std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > xpm_map; static std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > xpm_map;
const char* const *get_xpm_data (std::string path); 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__ */ #endif /* __ardour_gtk_utils_h__ */

View file

@ -279,14 +279,12 @@ VisualTimeAxis::remove_this_time_axis(void* src)
Gtkmm2ext::Choice prompter (prompt, choices); Gtkmm2ext::Choice prompter (prompt, choices);
if (prompter.run () == RESPONSE_ACCEPT) { if (prompter.run () == 0) {
if (prompter.get_choice() == 0) { /*
/* defer to idle loop, otherwise we'll delete this object
defer to idle loop, otherwise we'll delete this object while we're still inside this function ...
while we're still inside this function ... */
*/ Glib::signal_idle().connect(bind(sigc::ptr_fun(&VisualTimeAxis::idle_remove_this_time_axis), this, src));
Glib::signal_idle().connect(bind(sigc::ptr_fun(&VisualTimeAxis::idle_remove_this_time_axis), this, src));
}
} }
} }

View file

@ -640,13 +640,17 @@ class Session : public sigc::trackable, public Stateful
/* source management */ /* source management */
struct import_status : public InterThreadInfo { struct import_status : public InterThreadInfo {
string doing_what; string doing_what;
/* control info */
bool multichan;
bool sample_convert;
volatile bool freeze;
string pathname;
/* result */
std::vector<AudioRegion*> new_regions;
/* control info */
bool multichan;
bool sample_convert;
volatile bool freeze;
string pathname;
}; };
int import_audiofile (import_status&); int import_audiofile (import_status&);

View file

@ -61,11 +61,12 @@ Session::import_audiofile (import_status& status)
jack_nframes_t so_far; jack_nframes_t so_far;
char buf[PATH_MAX+1]; char buf[PATH_MAX+1];
int ret = -1; int ret = -1;
vector<AudioRegion *> new_regions;
vector<string> new_paths; vector<string> new_paths;
struct tm* now; struct tm* now;
string tmp_convert_file; string tmp_convert_file;
status.new_regions.clear ();
if ((in = sf_open (status.pathname.c_str(), SFM_READ, &info)) == 0) { if ((in = sf_open (status.pathname.c_str(), SFM_READ, &info)) == 0) {
error << string_compose(_("Import: cannot open input sound file \"%1\""), status.pathname) << endmsg; error << string_compose(_("Import: cannot open input sound file \"%1\""), status.pathname) << endmsg;
return -1; return -1;
@ -214,7 +215,7 @@ Session::import_audiofile (import_status& status)
AudioRegion *r = new AudioRegion (sources, 0, newfiles[0]->length(), region_name_from_path (PBD::basename(basepath)), AudioRegion *r = new AudioRegion (sources, 0, newfiles[0]->length(), region_name_from_path (PBD::basename(basepath)),
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile)); 0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile));
new_regions.push_back (r); status.new_regions.push_back (r);
} else { } else {
for (n = 0; n < nfiles && !status.cancel; ++n) { for (n = 0; n < nfiles && !status.cancel; ++n) {
@ -230,7 +231,7 @@ Session::import_audiofile (import_status& status)
AudioRegion *r = new AudioRegion (*newfiles[n], 0, newfiles[n]->length(), region_name_from_path (PBD::basename (newfiles[n]->name())), AudioRegion *r = new AudioRegion (*newfiles[n], 0, newfiles[n]->length(), region_name_from_path (PBD::basename (newfiles[n]->name())),
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile | AudioRegion::Import)); 0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile | AudioRegion::Import));
new_regions.push_back (r); status.new_regions.push_back (r);
} }
} }
@ -259,7 +260,7 @@ Session::import_audiofile (import_status& status)
} }
if (status.cancel) { if (status.cancel) {
for (vector<AudioRegion *>::iterator i = new_regions.begin(); i != new_regions.end(); ++i) { for (vector<AudioRegion *>::iterator i = status.new_regions.begin(); i != status.new_regions.end(); ++i) {
delete *i; delete *i;
} }

View file

@ -26,28 +26,30 @@ using namespace Gtkmm2ext;
using namespace sigc; using namespace sigc;
using namespace Gtk; using namespace Gtk;
Choice::Choice (string prompt, vector<string> choices) Choice::Choice (string prompt, vector<string> choices, bool center)
{ {
int n; int n;
vector<string>::iterator i; vector<string>::iterator i;
set_position (Gtk::WIN_POS_CENTER); if (center) {
set_position (Gtk::WIN_POS_CENTER);
} else {
set_position (Gtk::WIN_POS_MOUSE);
}
set_name ("ChoiceWindow"); set_name ("ChoiceWindow");
Label* label = manage (new Label (prompt)); Label* label = manage (new Label (prompt));
label->show (); label->show ();
get_vbox()->set_border_width (12);
get_vbox()->pack_start (*label); get_vbox()->pack_start (*label);
set_has_separator (false);
for (n = 0, i = choices.begin(); i != choices.end(); ++i, ++n) { for (n = 0, i = choices.begin(); i != choices.end(); ++i, ++n) {
add_button (*i, n);
Button* button;
button = add_button (*i, RESPONSE_ACCEPT);
button->signal_button_release_event().connect (bind (mem_fun (*this, &Choice::choice_made), n), false);
} }
which_choice = -1;
} }
void void
@ -60,17 +62,3 @@ Choice::on_realize ()
Choice::~Choice () Choice::~Choice ()
{ {
} }
bool
Choice::choice_made (GdkEventButton* ev, int nbutton)
{
which_choice = nbutton;
response (RESPONSE_ACCEPT);
return true;
}
int
Choice::get_choice ()
{
return which_choice;
}

View file

@ -10,17 +10,11 @@ namespace Gtkmm2ext {
class Choice : public Gtk::Dialog class Choice : public Gtk::Dialog
{ {
public: public:
Choice (std::string prompt, std::vector<std::string> choices); Choice (std::string prompt, std::vector<std::string> choices, bool center = true);
virtual ~Choice (); virtual ~Choice ();
int get_choice ();
protected: protected:
void on_realize (); void on_realize ();
private:
int which_choice;
bool choice_made (GdkEventButton* ev, int nbutton);
}; };
} /* namespace */ } /* namespace */

View file

@ -26,8 +26,6 @@
#include <pbd/pthread_utils.h> #include <pbd/pthread_utils.h>
using std::string; using std::string;
using std::cerr;
using std::endl;
typedef std::map<string,pthread_t> ThreadMap; typedef std::map<string,pthread_t> ThreadMap;
static ThreadMap all_threads; static ThreadMap all_threads;