mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 03:36:32 +01:00
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:
parent
004a49b0c7
commit
3aa346b253
25 changed files with 647 additions and 647 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@
|
|||
<separator/>
|
||||
<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'/>
|
||||
<menuitem action='ExportSelection'/>
|
||||
|
|
@ -308,6 +314,6 @@
|
|||
<menuitem action='SortBySourceFilesystem'/>
|
||||
</menu>
|
||||
<separator/>
|
||||
<menuitem action='addExternalRegion'/>
|
||||
<menuitem action='addExternalAudioToRegionList'/>
|
||||
</popup>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -53,3 +53,7 @@ DISPLAYCONTROL(FollowPlayhead)
|
|||
DISPLAYCONTROL(ShowMeasures)
|
||||
DISPLAYCONTROL(ShowWaveforms)
|
||||
DISPLAYCONTROL(ShowWaveformsRecording)
|
||||
|
||||
IMPORTMODE(ImportAsRegion)
|
||||
IMPORTMODE(ImportAsTrack)
|
||||
IMPORTMODE(ImportToTrack)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
@ -340,7 +341,16 @@ Editor::register_actions ()
|
|||
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));
|
||||
|
|
|
|||
395
gtk2_ardour/editor_audio_import.cc
Normal file
395
gtk2_ardour/editor_audio_import.cc
Normal 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);
|
||||
}
|
||||
|
||||
|
|
@ -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,24 +484,20 @@ 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:
|
||||
context->drag_finish (true, false, time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -199,11 +199,7 @@ Do you really want to destroy %1 ?"),
|
|||
|
||||
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,11 +3071,9 @@ Editor::remove_last_capture ()
|
|||
|
||||
Gtkmm2ext::Choice prompter (prompt, choices);
|
||||
|
||||
if (prompter.run () == RESPONSE_ACCEPT) {
|
||||
if (prompter.get_choice() == 0) {
|
||||
if (prompter.run () == 0) {
|
||||
session->remove_last_capture ();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
session->remove_last_capture();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -900,11 +900,9 @@ RedirectBox::clear_redirects()
|
|||
|
||||
Gtkmm2ext::Choice prompter (prompt, choices);
|
||||
|
||||
if (prompter.run () == RESPONSE_ACCEPT) {
|
||||
if (prompter.get_choice() == 0) {
|
||||
if (prompter.run () == 0) {
|
||||
_route.clear_redirects (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -703,13 +703,9 @@ RouteUI::remove_this_route ()
|
|||
|
||||
Choice prompter (prompt, choices);
|
||||
|
||||
prompter.show_all ();
|
||||
|
||||
if (prompter.run () == RESPONSE_ACCEPT) {
|
||||
if (prompter.get_choice() == 0) {
|
||||
if (prompter.run () == 0) {
|
||||
Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
:
|
||||
|
|
@ -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")),
|
||||
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());
|
||||
|
||||
embed_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::embed_clicked));
|
||||
import_btn.signal_clicked().connect (mem_fun (*this, &SoundFileOmega::import_clicked));
|
||||
Gtkmm2ext::set_popdown_strings (mode_combo, mode_strings);
|
||||
|
||||
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 ();
|
||||
}
|
||||
|
||||
void
|
||||
SoundFileOmega::embed_clicked ()
|
||||
bool
|
||||
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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -111,6 +113,7 @@ class SoundFileBrowser : public ArdourDialog
|
|||
virtual ~SoundFileBrowser () {};
|
||||
|
||||
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::ComboBoxText mode_combo;
|
||||
|
||||
void embed_clicked ();
|
||||
void import_clicked ();
|
||||
void mode_changed ();
|
||||
|
||||
static std::vector<std::string> mode_strings;
|
||||
};
|
||||
|
||||
#endif // __ardour_sfdb_ui_h__
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -279,15 +279,13 @@ VisualTimeAxis::remove_this_time_axis(void* src)
|
|||
|
||||
Gtkmm2ext::Choice prompter (prompt, choices);
|
||||
|
||||
if (prompter.run () == RESPONSE_ACCEPT) {
|
||||
if (prompter.get_choice() == 0) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -647,6 +647,10 @@ class Session : public sigc::trackable, public Stateful
|
|||
bool sample_convert;
|
||||
volatile bool freeze;
|
||||
string pathname;
|
||||
|
||||
/* result */
|
||||
std::vector<AudioRegion*> new_regions;
|
||||
|
||||
};
|
||||
|
||||
int import_audiofile (import_status&);
|
||||
|
|
|
|||
|
|
@ -61,11 +61,12 @@ Session::import_audiofile (import_status& status)
|
|||
jack_nframes_t so_far;
|
||||
char buf[PATH_MAX+1];
|
||||
int ret = -1;
|
||||
vector<AudioRegion *> new_regions;
|
||||
vector<string> new_paths;
|
||||
struct tm* now;
|
||||
string tmp_convert_file;
|
||||
|
||||
status.new_regions.clear ();
|
||||
|
||||
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;
|
||||
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)),
|
||||
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile));
|
||||
|
||||
new_regions.push_back (r);
|
||||
status.new_regions.push_back (r);
|
||||
|
||||
} else {
|
||||
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())),
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,28 +26,30 @@ using namespace Gtkmm2ext;
|
|||
using namespace sigc;
|
||||
using namespace Gtk;
|
||||
|
||||
Choice::Choice (string prompt, vector<string> choices)
|
||||
Choice::Choice (string prompt, vector<string> choices, bool center)
|
||||
{
|
||||
int n;
|
||||
vector<string>::iterator i;
|
||||
|
||||
if (center) {
|
||||
set_position (Gtk::WIN_POS_CENTER);
|
||||
} else {
|
||||
set_position (Gtk::WIN_POS_MOUSE);
|
||||
}
|
||||
|
||||
set_name ("ChoiceWindow");
|
||||
|
||||
Label* label = manage (new Label (prompt));
|
||||
label->show ();
|
||||
|
||||
get_vbox()->set_border_width (12);
|
||||
get_vbox()->pack_start (*label);
|
||||
|
||||
set_has_separator (false);
|
||||
|
||||
for (n = 0, i = choices.begin(); i != choices.end(); ++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);
|
||||
add_button (*i, n);
|
||||
}
|
||||
|
||||
which_choice = -1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -60,17 +62,3 @@ Choice::on_realize ()
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,11 @@ namespace Gtkmm2ext {
|
|||
class Choice : public Gtk::Dialog
|
||||
{
|
||||
public:
|
||||
Choice (std::string prompt, std::vector<std::string> choices);
|
||||
Choice (std::string prompt, std::vector<std::string> choices, bool center = true);
|
||||
virtual ~Choice ();
|
||||
|
||||
int get_choice ();
|
||||
|
||||
protected:
|
||||
void on_realize ();
|
||||
|
||||
private:
|
||||
int which_choice;
|
||||
bool choice_made (GdkEventButton* ev, int nbutton);
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@
|
|||
#include <pbd/pthread_utils.h>
|
||||
|
||||
using std::string;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
typedef std::map<string,pthread_t> ThreadMap;
|
||||
static ThreadMap all_threads;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue