mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-11 09:06:33 +01:00
Add Import from session -functionality
git-svn-id: svn://localhost/ardour2/branches/3.0@3805 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
10d57b266c
commit
572fa80aa7
27 changed files with 2120 additions and 9 deletions
|
|
@ -223,6 +223,7 @@ route_time_axis.cc
|
||||||
route_ui.cc
|
route_ui.cc
|
||||||
selection.cc
|
selection.cc
|
||||||
send_ui.cc
|
send_ui.cc
|
||||||
|
session_import_dialog.cc
|
||||||
session_metadata_dialog.cc
|
session_metadata_dialog.cc
|
||||||
sfdb_ui.cc
|
sfdb_ui.cc
|
||||||
simpleline.cc
|
simpleline.cc
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
<menuitem action='AddTrackBus'/>
|
<menuitem action='AddTrackBus'/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<menuitem action='addExistingAudioFiles'/>
|
<menuitem action='addExistingAudioFiles'/>
|
||||||
|
<menuitem action='importFromSession'/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<menu name='Export' action='Export'>
|
<menu name='Export' action='Export'>
|
||||||
<menuitem action='ExportAudio'/>
|
<menuitem action='ExportAudio'/>
|
||||||
|
|
|
||||||
|
|
@ -1213,6 +1213,7 @@ class Editor : public PublicEditor
|
||||||
|
|
||||||
void add_external_audio_action (Editing::ImportMode);
|
void add_external_audio_action (Editing::ImportMode);
|
||||||
void external_audio_dialog ();
|
void external_audio_dialog ();
|
||||||
|
void session_import_dialog ();
|
||||||
|
|
||||||
int check_whether_and_how_to_import(string, bool all_or_nothing = true);
|
int check_whether_and_how_to_import(string, bool all_or_nothing = true);
|
||||||
bool check_multichannel_status (const std::vector<Glib::ustring>& paths);
|
bool check_multichannel_status (const std::vector<Glib::ustring>& paths);
|
||||||
|
|
|
||||||
|
|
@ -754,6 +754,8 @@ Editor::register_actions ()
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
|
act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
|
|
||||||
|
+ ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import From Session"), mem_fun(*this, &Editor::session_import_dialog));
|
||||||
|
|
||||||
act = ActionManager::register_toggle_action (editor_actions, X_("toggle-waveform-visible"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility));
|
act = ActionManager::register_toggle_action (editor_actions, X_("toggle-waveform-visible"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility));
|
||||||
ActionManager::track_selection_sensitive_actions.push_back (act);
|
ActionManager::track_selection_sensitive_actions.push_back (act);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
#include "editing.h"
|
#include "editing.h"
|
||||||
#include "audio_time_axis.h"
|
#include "audio_time_axis.h"
|
||||||
#include "midi_time_axis.h"
|
#include "midi_time_axis.h"
|
||||||
|
#include "session_import_dialog.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
@ -184,6 +185,14 @@ Editor::external_audio_dialog ()
|
||||||
} while (keepRunning);
|
} while (keepRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Editor::session_import_dialog ()
|
||||||
|
{
|
||||||
|
SessionImportDialog dialog (*session);
|
||||||
|
ensure_float (dialog);
|
||||||
|
dialog.run ();
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::map<PBD::ID,boost::shared_ptr<ARDOUR::Source> > SourceMap;
|
typedef std::map<PBD::ID,boost::shared_ptr<ARDOUR::Source> > SourceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,35 @@ PlaylistSelector::show_for (RouteUI* ruix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add unassigned (imported) playlists to the list
|
||||||
|
list<boost::shared_ptr<Playlist> > unassigned;
|
||||||
|
session->unassigned_playlists (unassigned);
|
||||||
|
|
||||||
|
TreeModel::Row row;
|
||||||
|
TreeModel::Row* selected_row = 0;
|
||||||
|
TreePath this_path;
|
||||||
|
|
||||||
|
row = *(model->append (others.children()));
|
||||||
|
row[columns.text] = _("Imported");
|
||||||
|
proxy = row[columns.playlist];
|
||||||
|
proxy.reset ();
|
||||||
|
|
||||||
|
for (list<boost::shared_ptr<Playlist> >::iterator p = unassigned.begin(); p != unassigned.end(); ++p) {
|
||||||
|
TreeModel::Row child_row;
|
||||||
|
|
||||||
|
child_row = *(model->append (row.children()));
|
||||||
|
child_row[columns.text] = (*p)->name();
|
||||||
|
child_row[columns.playlist] = *p;
|
||||||
|
|
||||||
|
if (*p == this_ds->playlist()) {
|
||||||
|
selected_row = &child_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_row != 0) {
|
||||||
|
tree.get_selection()->select (*selected_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
show_all ();
|
show_all ();
|
||||||
select_connection = tree.get_selection()->signal_changed().connect (mem_fun(*this, &PlaylistSelector::selection_changed));
|
select_connection = tree.get_selection()->signal_changed().connect (mem_fun(*this, &PlaylistSelector::selection_changed));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
321
gtk2_ardour/session_import_dialog.cc
Normal file
321
gtk2_ardour/session_import_dialog.cc
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "session_import_dialog.h"
|
||||||
|
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
|
||||||
|
#include <ardour/audio_region_importer.h>
|
||||||
|
#include <ardour/audio_playlist_importer.h>
|
||||||
|
#include <ardour/location_importer.h>
|
||||||
|
#include <ardour/tempo_map_importer.h>
|
||||||
|
|
||||||
|
#include <gtkmm2ext/utils.h>
|
||||||
|
#include <gtkmm2ext/window_title.h>
|
||||||
|
|
||||||
|
#include "prompter.h"
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
SessionImportDialog::SessionImportDialog (ARDOUR::Session & target) :
|
||||||
|
ArdourDialog (_("Import from session")),
|
||||||
|
target (target),
|
||||||
|
file_browse_button (_("Browse"))
|
||||||
|
{
|
||||||
|
// File entry
|
||||||
|
file_entry.set_name ("ImportFileNameEntry");
|
||||||
|
file_entry.set_text ("/");
|
||||||
|
Gtkmm2ext::set_size_request_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
|
||||||
|
|
||||||
|
file_browse_button.set_name ("EditorGTKButton");
|
||||||
|
file_browse_button.signal_clicked().connect (mem_fun(*this, &SessionImportDialog::browse));
|
||||||
|
|
||||||
|
file_hbox.set_spacing (5);
|
||||||
|
file_hbox.set_border_width (5);
|
||||||
|
file_hbox.pack_start (file_entry, true, true);
|
||||||
|
file_hbox.pack_start (file_browse_button, false, false);
|
||||||
|
|
||||||
|
file_frame.add (file_hbox);
|
||||||
|
file_frame.set_border_width (5);
|
||||||
|
file_frame.set_name ("ImportFrom");
|
||||||
|
file_frame.set_label (_("Import from Session"));
|
||||||
|
|
||||||
|
get_vbox()->pack_start (file_frame, false, false);
|
||||||
|
|
||||||
|
// Session browser
|
||||||
|
session_tree = Gtk::TreeStore::create (sb_cols);
|
||||||
|
session_browser.set_model (session_tree);
|
||||||
|
|
||||||
|
session_browser.set_name ("SessionBrowser");
|
||||||
|
session_browser.append_column (_("Elements"), sb_cols.name);
|
||||||
|
session_browser.append_column_editable (_("Import"), sb_cols.queued);
|
||||||
|
session_browser.get_column(0)->set_min_width (180);
|
||||||
|
session_browser.get_column(1)->set_min_width (40);
|
||||||
|
session_browser.get_column(1)->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE);
|
||||||
|
|
||||||
|
session_scroll.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
|
||||||
|
session_scroll.add (session_browser);
|
||||||
|
session_scroll.set_size_request (220, 400);
|
||||||
|
|
||||||
|
// Connect signals
|
||||||
|
Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *> (session_browser.get_column_cell_renderer (1));
|
||||||
|
toggle->signal_toggled().connect(mem_fun (*this, &SessionImportDialog::update));
|
||||||
|
session_browser.signal_row_activated().connect(mem_fun (*this, &SessionImportDialog::show_info));
|
||||||
|
|
||||||
|
get_vbox()->pack_start (session_scroll, false, false);
|
||||||
|
|
||||||
|
// Tooltips
|
||||||
|
session_browser.set_has_tooltip();
|
||||||
|
session_browser.signal_query_tooltip().connect(mem_fun(*this, &SessionImportDialog::query_tooltip));
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||||
|
cancel_button->signal_clicked().connect (mem_fun (*this, &SessionImportDialog::end_dialog));
|
||||||
|
ok_button = add_button (_("Import"), Gtk::RESPONSE_ACCEPT);
|
||||||
|
ok_button->signal_clicked().connect (mem_fun (*this, &SessionImportDialog::do_merge));
|
||||||
|
|
||||||
|
// prompt signals
|
||||||
|
ElementImporter::Rename.connect (mem_fun (*this, &SessionImportDialog::open_rename_dialog));
|
||||||
|
ElementImporter::Prompt.connect (mem_fun (*this, &SessionImportDialog::open_prompt_dialog));
|
||||||
|
|
||||||
|
// Finalize
|
||||||
|
show_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::load_session (const string& filename)
|
||||||
|
{
|
||||||
|
tree.read (filename);
|
||||||
|
AudioRegionImportHandler *region_handler;
|
||||||
|
|
||||||
|
region_handler = new AudioRegionImportHandler (tree, target);
|
||||||
|
handlers.push_back (HandlerPtr(region_handler));
|
||||||
|
handlers.push_back (HandlerPtr(new AudioPlaylistImportHandler (tree, target, *region_handler)));
|
||||||
|
handlers.push_back (HandlerPtr(new UnusedAudioPlaylistImportHandler (tree, target, *region_handler)));
|
||||||
|
handlers.push_back (HandlerPtr(new LocationImportHandler (tree, target)));
|
||||||
|
handlers.push_back (HandlerPtr(new TempoMapImportHandler (tree, target)));
|
||||||
|
|
||||||
|
fill_list();
|
||||||
|
|
||||||
|
if (ElementImportHandler::dirty()) {
|
||||||
|
// Warn user
|
||||||
|
string txt = _("Some elements had errors in them. Please see the log for details");
|
||||||
|
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
|
||||||
|
msg.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::fill_list ()
|
||||||
|
{
|
||||||
|
session_tree->clear();
|
||||||
|
|
||||||
|
// Loop through element types
|
||||||
|
for (HandlerList::iterator handler = handlers.begin(); handler != handlers.end(); ++handler) {
|
||||||
|
Gtk::TreeModel::iterator iter = session_tree->append();
|
||||||
|
Gtk::TreeModel::Row row = *iter;
|
||||||
|
row[sb_cols.name] = (*handler)->get_info();
|
||||||
|
row[sb_cols.queued] = false;
|
||||||
|
row[sb_cols.element] = ElementPtr(); // "Null" pointer
|
||||||
|
|
||||||
|
// Loop through elements
|
||||||
|
ElementList &elements = (*handler)->elements;
|
||||||
|
for (ElementList::iterator element = elements.begin(); element != elements.end(); ++element) {
|
||||||
|
iter = session_tree->append(row.children());
|
||||||
|
Gtk::TreeModel::Row child = *iter;
|
||||||
|
child[sb_cols.name] = (*element)->get_name();
|
||||||
|
child[sb_cols.queued] = false;
|
||||||
|
child[sb_cols.element] = *element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::browse ()
|
||||||
|
{
|
||||||
|
Gtk::FileChooserDialog dialog(_("Import from session"), browse_action());
|
||||||
|
dialog.set_transient_for(*this);
|
||||||
|
dialog.set_filename (file_entry.get_text());
|
||||||
|
|
||||||
|
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||||
|
dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
|
int result = dialog.run();
|
||||||
|
|
||||||
|
if (result == Gtk::RESPONSE_OK) {
|
||||||
|
string filename = dialog.get_filename();
|
||||||
|
|
||||||
|
if (filename.length()) {
|
||||||
|
file_entry.set_text (filename);
|
||||||
|
load_session (filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::do_merge ()
|
||||||
|
{
|
||||||
|
|
||||||
|
// element types
|
||||||
|
Gtk::TreeModel::Children types = session_browser.get_model()->children();
|
||||||
|
Gtk::TreeModel::Children::iterator ti;
|
||||||
|
for (ti = types.begin(); ti != types.end(); ++ti) {
|
||||||
|
// elements
|
||||||
|
Gtk::TreeModel::Children elements = ti->children();
|
||||||
|
Gtk::TreeModel::Children::iterator ei;
|
||||||
|
for (ei = elements.begin(); ei != elements.end(); ++ei) {
|
||||||
|
if ((*ei)[sb_cols.queued]) {
|
||||||
|
ElementPtr element = (*ei)[sb_cols.element];
|
||||||
|
element->move();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_dialog();
|
||||||
|
|
||||||
|
if (ElementImportHandler::errors()) {
|
||||||
|
// Warn user
|
||||||
|
string txt = _("Some elements had errors in them. Please see the log for details");
|
||||||
|
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
|
||||||
|
msg.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::update (string path)
|
||||||
|
{
|
||||||
|
Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
|
||||||
|
|
||||||
|
// Select all elements if element type is selected
|
||||||
|
if (path.size() == 1) {
|
||||||
|
{
|
||||||
|
// Prompt user for verification
|
||||||
|
string txt = _("This will select all elements of this type!");
|
||||||
|
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
|
||||||
|
if (msg.run() == Gtk::RESPONSE_CANCEL) {
|
||||||
|
(*cell)[sb_cols.queued] = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::TreeModel::Children elements = cell->children();
|
||||||
|
Gtk::TreeModel::Children::iterator ei;
|
||||||
|
for (ei = elements.begin(); ei != elements.end(); ++ei) {
|
||||||
|
ElementPtr element = (*ei)[sb_cols.element];
|
||||||
|
if (element->prepare_move()) {
|
||||||
|
(*ei)[sb_cols.queued] = true;
|
||||||
|
} else {
|
||||||
|
(*cell)[sb_cols.queued] = false; // Not all are selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementPtr element = (*cell)[sb_cols.element];
|
||||||
|
if ((*cell)[sb_cols.queued]) {
|
||||||
|
if (!element->prepare_move()) {
|
||||||
|
(*cell)[sb_cols.queued] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
element->cancel_move();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::show_info(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column)
|
||||||
|
{
|
||||||
|
if (path.size() == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
|
||||||
|
ElementPtr element = (*cell)[sb_cols.element];
|
||||||
|
string info = element->get_info();
|
||||||
|
|
||||||
|
Gtk::MessageDialog msg (info, false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true);
|
||||||
|
msg.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SessionImportDialog::query_tooltip(int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip)
|
||||||
|
{
|
||||||
|
Gtk::TreeModel::Path path;
|
||||||
|
Gtk::TreeViewColumn* column;
|
||||||
|
int cell_x, cell_y;
|
||||||
|
|
||||||
|
// Get element
|
||||||
|
session_browser.get_path_at_pos (x, y, path, column, cell_x, cell_y);
|
||||||
|
if (path.gobj() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Gtk::TreeModel::iterator row = session_browser.get_model()->get_iter (path);
|
||||||
|
//--row; // FIXME Strange offset in rows, if someone figures this out, please fix
|
||||||
|
ElementPtr element = (*row)[sb_cols.element];
|
||||||
|
if (element.get() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare tooltip
|
||||||
|
tooltip->set_text(element->get_info());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionImportDialog::end_dialog ()
|
||||||
|
{
|
||||||
|
hide_all();
|
||||||
|
|
||||||
|
set_modal (false);
|
||||||
|
ok_button->set_sensitive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, string>
|
||||||
|
SessionImportDialog::open_rename_dialog (string text, string name)
|
||||||
|
{
|
||||||
|
ArdourPrompter prompter(true);
|
||||||
|
string new_name;
|
||||||
|
|
||||||
|
prompter.set_name ("Prompter");
|
||||||
|
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
|
||||||
|
prompter.set_prompt (text);
|
||||||
|
prompter.set_initial_text (name);
|
||||||
|
|
||||||
|
if (prompter.run() == Gtk::RESPONSE_ACCEPT) {
|
||||||
|
prompter.get_result (new_name);
|
||||||
|
if (new_name.length()) {
|
||||||
|
name = new_name;
|
||||||
|
}
|
||||||
|
return std::make_pair (true, new_name);
|
||||||
|
}
|
||||||
|
return std::make_pair (false, new_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SessionImportDialog::open_prompt_dialog (string text)
|
||||||
|
{
|
||||||
|
Gtk::MessageDialog msg (text, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
|
||||||
|
if (msg.run() == Gtk::RESPONSE_OK) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
101
gtk2_ardour/session_import_dialog.h
Normal file
101
gtk2_ardour/session_import_dialog.h
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __session_import_dialog_h__
|
||||||
|
#define __session_import_dialog_h__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <gtkmm.h>
|
||||||
|
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
|
||||||
|
#include "ardour_dialog.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class Session;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionImportDialog : public ArdourDialog
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::shared_ptr<ARDOUR::ElementImportHandler> HandlerPtr;
|
||||||
|
typedef std::list<HandlerPtr> HandlerList;
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<ARDOUR::ElementImporter> ElementPtr;
|
||||||
|
typedef std::list<ElementPtr> ElementList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SessionImportDialog (ARDOUR::Session & target);
|
||||||
|
|
||||||
|
virtual Gtk::FileChooserAction browse_action() const { return Gtk::FILE_CHOOSER_ACTION_OPEN; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void load_session (const string& filename);
|
||||||
|
void fill_list ();
|
||||||
|
void browse ();
|
||||||
|
void do_merge ();
|
||||||
|
void end_dialog ();
|
||||||
|
void update (string path);
|
||||||
|
void show_info(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||||
|
bool query_tooltip(int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip);
|
||||||
|
|
||||||
|
std::pair<bool, string> open_rename_dialog (string text, string name);
|
||||||
|
bool open_prompt_dialog (string text);
|
||||||
|
|
||||||
|
// Data
|
||||||
|
HandlerList handlers;
|
||||||
|
XMLTree tree;
|
||||||
|
ARDOUR::Session ⌖
|
||||||
|
|
||||||
|
// GUI
|
||||||
|
Gtk::Frame file_frame;
|
||||||
|
Gtk::HBox file_hbox;
|
||||||
|
Gtk::Entry file_entry;
|
||||||
|
Gtk::Button file_browse_button;
|
||||||
|
|
||||||
|
struct SessionBrowserColumns : public Gtk::TreeModel::ColumnRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Gtk::TreeModelColumn<std::string> name;
|
||||||
|
Gtk::TreeModelColumn<bool> queued;
|
||||||
|
Gtk::TreeModelColumn<ElementPtr> element;
|
||||||
|
|
||||||
|
SessionBrowserColumns() { add (name); add (queued); add (element); }
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionBrowserColumns sb_cols;
|
||||||
|
Glib::RefPtr<Gtk::TreeStore> session_tree;
|
||||||
|
Gtk::TreeView session_browser;
|
||||||
|
Gtk::ScrolledWindow session_scroll;
|
||||||
|
|
||||||
|
Gtk::Button* ok_button;
|
||||||
|
Gtk::Button* cancel_button;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -36,6 +36,7 @@ audio_buffer.cc
|
||||||
audio_diskstream.cc
|
audio_diskstream.cc
|
||||||
audio_library.cc
|
audio_library.cc
|
||||||
audio_playlist.cc
|
audio_playlist.cc
|
||||||
|
audio_playlist_importer.cc
|
||||||
audio_port.cc
|
audio_port.cc
|
||||||
audio_track.cc
|
audio_track.cc
|
||||||
audioanalyser.cc
|
audioanalyser.cc
|
||||||
|
|
@ -43,6 +44,7 @@ audioengine.cc
|
||||||
audiofile_tagger.cc
|
audiofile_tagger.cc
|
||||||
audiofilesource.cc
|
audiofilesource.cc
|
||||||
audioregion.cc
|
audioregion.cc
|
||||||
|
audio_region_importer.cc
|
||||||
audiosource.cc
|
audiosource.cc
|
||||||
auditioner.cc
|
auditioner.cc
|
||||||
auto_bundle.cc
|
auto_bundle.cc
|
||||||
|
|
@ -64,6 +66,8 @@ cycle_timer.cc
|
||||||
default_click.cc
|
default_click.cc
|
||||||
directory_names.cc
|
directory_names.cc
|
||||||
diskstream.cc
|
diskstream.cc
|
||||||
|
element_importer.cc
|
||||||
|
element_import_handler.cc
|
||||||
enums.cc
|
enums.cc
|
||||||
event_type_map.cc
|
event_type_map.cc
|
||||||
export_channel_configuration.cc
|
export_channel_configuration.cc
|
||||||
|
|
@ -96,6 +100,7 @@ jack_port.cc
|
||||||
jack_slave.cc
|
jack_slave.cc
|
||||||
ladspa_plugin.cc
|
ladspa_plugin.cc
|
||||||
location.cc
|
location.cc
|
||||||
|
location_importer.cc
|
||||||
meter.cc
|
meter.cc
|
||||||
midi_buffer.cc
|
midi_buffer.cc
|
||||||
midi_clock_slave.cc
|
midi_clock_slave.cc
|
||||||
|
|
@ -159,6 +164,7 @@ svn_revision.cc
|
||||||
tape_file_matcher.cc
|
tape_file_matcher.cc
|
||||||
template_utils.cc
|
template_utils.cc
|
||||||
tempo.cc
|
tempo.cc
|
||||||
|
tempo_map_importer.cc
|
||||||
track.cc
|
track.cc
|
||||||
transient_detector.cc
|
transient_detector.cc
|
||||||
user_bundle.cc
|
user_bundle.cc
|
||||||
|
|
|
||||||
87
libs/ardour/ardour/audio_playlist_importer.h
Normal file
87
libs/ardour/ardour/audio_playlist_importer.h
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_audio_playlist_importer_h__
|
||||||
|
#define __ardour_audio_playlist_importer_h__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
#include <pbd/id.h>
|
||||||
|
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class AudioRegionImportHandler;
|
||||||
|
class AudioRegionImporter;
|
||||||
|
|
||||||
|
class AudioPlaylistImportHandler : public ElementImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler, const char * nodename = "Playlists");
|
||||||
|
virtual ~AudioPlaylistImportHandler () {}
|
||||||
|
virtual string get_info () const;
|
||||||
|
|
||||||
|
void get_regions (XMLNode const & node, ElementList & list);
|
||||||
|
void update_region_id (XMLProperty* id_prop);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AudioRegionImportHandler & region_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnusedAudioPlaylistImportHandler : public AudioPlaylistImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnusedAudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler) :
|
||||||
|
AudioPlaylistImportHandler (source, session, region_handler, X_("UnusedPlaylists")) { }
|
||||||
|
string get_info () const { return _("Audio Playlists (unused)"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioPlaylistImporter : public ElementImporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node);
|
||||||
|
|
||||||
|
string get_info () const;
|
||||||
|
bool prepare_move ();
|
||||||
|
void cancel_move ();
|
||||||
|
void move ();
|
||||||
|
|
||||||
|
void set_diskstream (PBD::ID const & id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::list<boost::shared_ptr<AudioRegionImporter> > RegionList;
|
||||||
|
|
||||||
|
AudioPlaylistImportHandler & handler;
|
||||||
|
XMLNode xml_playlist;
|
||||||
|
PBD::ID diskstream_id;
|
||||||
|
RegionList regions;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
107
libs/ardour/ardour/audio_region_importer.h
Normal file
107
libs/ardour/ardour/audio_region_importer.h
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_audio_region_importer_h__
|
||||||
|
#define __ardour_audio_region_importer_h__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
#include <pbd/id.h>
|
||||||
|
#include <pbd/filesystem.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Region;
|
||||||
|
|
||||||
|
class AudioRegionImportHandler : public ElementImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Inerface implementation
|
||||||
|
AudioRegionImportHandler (XMLTree const & source, Session & session);
|
||||||
|
string get_info () const;
|
||||||
|
|
||||||
|
void create_regions_from_children (XMLNode const & node, ElementList & list);
|
||||||
|
|
||||||
|
// Source management
|
||||||
|
bool check_source (string const & filename) const;
|
||||||
|
void add_source (string const & filename, boost::shared_ptr<Source> const & source);
|
||||||
|
boost::shared_ptr<Source> const & get_source (string const & filename) const;
|
||||||
|
|
||||||
|
// Id management
|
||||||
|
void register_id (PBD::ID & old_id, PBD::ID & new_id);
|
||||||
|
PBD::ID const & get_new_id (PBD::ID & old_id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Source management
|
||||||
|
typedef std::map<string, boost::shared_ptr<Source> > SourceMap;
|
||||||
|
typedef std::pair<string, boost::shared_ptr<Source> > SourcePair;
|
||||||
|
SourceMap sources;
|
||||||
|
|
||||||
|
// Id management
|
||||||
|
typedef std::map<PBD::ID, PBD::ID> IdMap;
|
||||||
|
typedef std::pair<PBD::ID, PBD::ID> IdPair;
|
||||||
|
IdMap id_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioRegionImporter : public ElementImporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioRegionImporter (XMLTree const & source, Session & session, AudioRegionImportHandler & handler, XMLNode const & node);
|
||||||
|
|
||||||
|
// Interface implementation
|
||||||
|
string get_info () const;
|
||||||
|
bool prepare_move ();
|
||||||
|
void cancel_move ();
|
||||||
|
void move ();
|
||||||
|
|
||||||
|
// other stuff
|
||||||
|
void add_sources_to_session ();
|
||||||
|
XMLNode const & get_xml ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
XMLNode xml_region;
|
||||||
|
AudioRegionImportHandler & handler;
|
||||||
|
PBD::ID old_id;
|
||||||
|
PBD::ID id;
|
||||||
|
std::list<string> filenames;
|
||||||
|
|
||||||
|
bool parse_xml_region ();
|
||||||
|
bool parse_source_xml ();
|
||||||
|
PBD::sys::path get_sound_dir (XMLTree const & tree);
|
||||||
|
|
||||||
|
void prepare_region ();
|
||||||
|
void prepare_sources ();
|
||||||
|
std::vector<boost::shared_ptr<Region> > region;
|
||||||
|
bool region_prepared;
|
||||||
|
bool sources_prepared;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
110
libs/ardour/ardour/element_import_handler.h
Normal file
110
libs/ardour/ardour/element_import_handler.h
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_element_import_handler_h__
|
||||||
|
#define __ardour_element_import_handler_h__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
class XMLTree;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Session;
|
||||||
|
class ElementImporter;
|
||||||
|
|
||||||
|
/// Virtual interface class for element import handlers
|
||||||
|
class ElementImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<ElementImporter> ElementPtr;
|
||||||
|
typedef std::list<ElementPtr> ElementList;
|
||||||
|
|
||||||
|
/** ElementImportHandler constructor
|
||||||
|
* The constructor should find everything from the XML Tree it can handle
|
||||||
|
* and create respective Elements stored in elements.
|
||||||
|
*
|
||||||
|
* @param source XML tree to be parsed
|
||||||
|
* @see elements
|
||||||
|
*/
|
||||||
|
ElementImportHandler (XMLTree const & source, ARDOUR::Session & session) :
|
||||||
|
source (source), session (session) { }
|
||||||
|
|
||||||
|
virtual ~ElementImportHandler ();
|
||||||
|
|
||||||
|
/** Gets a textual representation of the element type
|
||||||
|
* @return textual representation of element type
|
||||||
|
*/
|
||||||
|
virtual string get_info () const = 0;
|
||||||
|
|
||||||
|
/// Elements this handler handles
|
||||||
|
ElementList elements;
|
||||||
|
|
||||||
|
/* For checking duplicates names against queued elements */
|
||||||
|
|
||||||
|
/** Checks whether or not an element with some name is queued or not
|
||||||
|
* @param name name to check
|
||||||
|
* @return true if name is not used
|
||||||
|
*/
|
||||||
|
bool check_name (const string & name) const;
|
||||||
|
|
||||||
|
/// Adds name to the list of used names
|
||||||
|
void add_name (string name);
|
||||||
|
|
||||||
|
/// Removes name from the list of used names
|
||||||
|
void remove_name (const string & name);
|
||||||
|
|
||||||
|
/// Checks wheter or not all elements can be imported cleanly
|
||||||
|
static bool dirty () { return _dirty; }
|
||||||
|
|
||||||
|
/// Sets handler dirty
|
||||||
|
static void set_dirty () { _dirty = true; }
|
||||||
|
|
||||||
|
/// Checks wheter or not all elements were imported cleanly
|
||||||
|
static bool errors () { return _errors; }
|
||||||
|
|
||||||
|
/// Sets handler dirty
|
||||||
|
static void set_errors () { _errors = true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Source session XML tree
|
||||||
|
XMLTree const & source;
|
||||||
|
|
||||||
|
/// Destination session
|
||||||
|
ARDOUR::Session & session;
|
||||||
|
|
||||||
|
/// Session XML readability
|
||||||
|
static bool _dirty;
|
||||||
|
|
||||||
|
/// Errors post initialization
|
||||||
|
static bool _errors;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// List of names for duplicate checking
|
||||||
|
std::list<string> names;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
122
libs/ardour/ardour/element_importer.h
Normal file
122
libs/ardour/ardour/element_importer.h
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_element_importer_h__
|
||||||
|
#define __ardour_element_importer_h__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <sigc++/signal.h>
|
||||||
|
|
||||||
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
class XMLTree;
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
/// Virtual interface class for element importers
|
||||||
|
class ElementImporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ElementImporter (XMLTree const & source, ARDOUR::Session & session);
|
||||||
|
virtual ~ElementImporter () {};
|
||||||
|
|
||||||
|
/** Returns the element name
|
||||||
|
* @return the name of the element
|
||||||
|
*/
|
||||||
|
virtual string get_name () const { return name; };
|
||||||
|
|
||||||
|
/** Gets a textual representation of the element
|
||||||
|
* @return a textual representation on this specific element
|
||||||
|
*/
|
||||||
|
virtual string get_info () const = 0;
|
||||||
|
|
||||||
|
/** Prepares to move element
|
||||||
|
* Should take care of all tasks that need to be done
|
||||||
|
* before moving the element. This includes prompting
|
||||||
|
* the user for more information if necessary.
|
||||||
|
*
|
||||||
|
* If the element can be moved, queued should be set to true.
|
||||||
|
*
|
||||||
|
* @return whther or not the element could be prepared for moving
|
||||||
|
*/
|
||||||
|
virtual bool prepare_move () = 0;
|
||||||
|
|
||||||
|
/** Cancels moving of element
|
||||||
|
* If the element has been set to be moved, this cancels the move.
|
||||||
|
* queued should be set to false.
|
||||||
|
*/
|
||||||
|
virtual void cancel_move () = 0;
|
||||||
|
|
||||||
|
/** Moves the element to the taget session
|
||||||
|
* In addition to actually adding the element to the session
|
||||||
|
* changing ids, renaming files etc. should be taken care of.
|
||||||
|
*/
|
||||||
|
virtual void move () = 0;
|
||||||
|
|
||||||
|
/// Check if element is broken. Cannot be moved if broken.
|
||||||
|
bool broken () { return _broken; }
|
||||||
|
|
||||||
|
/// Signal that requests for anew name
|
||||||
|
static sigc::signal <std::pair<bool, string>, string, string> Rename;
|
||||||
|
|
||||||
|
/// Signal for ok/cancel prompting
|
||||||
|
static sigc::signal <bool, string> Prompt;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Source XML-tree
|
||||||
|
XMLTree const & source;
|
||||||
|
|
||||||
|
/// Target session
|
||||||
|
ARDOUR::Session & session;
|
||||||
|
|
||||||
|
/// Ture if the element has been prepared and queued for importing
|
||||||
|
bool queued;
|
||||||
|
|
||||||
|
/// Name of element
|
||||||
|
string name;
|
||||||
|
|
||||||
|
/// The sample rate of the session from which we are importing
|
||||||
|
nframes_t sample_rate;
|
||||||
|
|
||||||
|
/// Converts smpte time to a string
|
||||||
|
string smpte_to_string(SMPTE::Time & time) const;
|
||||||
|
|
||||||
|
/// Converts samples so that times match the sessions sample rate
|
||||||
|
nframes_t rate_convert_samples (nframes_t samples) const;
|
||||||
|
|
||||||
|
/// Converts samples so that times match the sessions sample rate (for straight use in XML)
|
||||||
|
string rate_convert_samples (string const & samples) const;
|
||||||
|
|
||||||
|
/// Set element broken
|
||||||
|
void set_broken () { _broken = true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _broken;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -99,6 +99,7 @@ class Location : public PBD::StatefulDestructible
|
||||||
void set_cd (bool yn, void *src);
|
void set_cd (bool yn, void *src);
|
||||||
void set_is_end (bool yn, void* src);
|
void set_is_end (bool yn, void* src);
|
||||||
void set_is_start (bool yn, void* src);
|
void set_is_start (bool yn, void* src);
|
||||||
|
void set_is_range_marker (bool yn, void* src);
|
||||||
|
|
||||||
bool is_auto_punch () const { return _flags & IsAutoPunch; }
|
bool is_auto_punch () const { return _flags & IsAutoPunch; }
|
||||||
bool is_auto_loop () const { return _flags & IsAutoLoop; }
|
bool is_auto_loop () const { return _flags & IsAutoLoop; }
|
||||||
|
|
|
||||||
63
libs/ardour/ardour/location_importer.h
Normal file
63
libs/ardour/ardour/location_importer.h
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_location_importer_h__
|
||||||
|
#define __ardour_location_importer_h__
|
||||||
|
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
#include <ardour/location.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class LocationImportHandler : public ElementImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LocationImportHandler (XMLTree const & source, Session & session);
|
||||||
|
string get_info () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LocationImporter : public ElementImporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node);
|
||||||
|
~LocationImporter ();
|
||||||
|
|
||||||
|
string get_info () const;
|
||||||
|
bool prepare_move ();
|
||||||
|
void cancel_move ();
|
||||||
|
void move ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
LocationImportHandler & handler;
|
||||||
|
XMLNode xml_location;
|
||||||
|
Location * location;
|
||||||
|
|
||||||
|
void parse_xml ();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -31,9 +31,9 @@ class Session;
|
||||||
class PlaylistFactory {
|
class PlaylistFactory {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistCreated;
|
static sigc::signal<void,boost::shared_ptr<Playlist>, bool> PlaylistCreated;
|
||||||
|
|
||||||
static boost::shared_ptr<Playlist> create (Session&, const XMLNode&, bool hidden = false);
|
static boost::shared_ptr<Playlist> create (Session&, const XMLNode&, bool hidden = false, bool unused = false);
|
||||||
static boost::shared_ptr<Playlist> create (DataType type, Session&, string name, bool hidden = false);
|
static boost::shared_ptr<Playlist> create (DataType type, Session&, string name, bool hidden = false);
|
||||||
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, string name, bool hidden = false);
|
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, string name, bool hidden = false);
|
||||||
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, nframes_t start, nframes_t cnt, string name, bool hidden = false);
|
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, nframes_t start, nframes_t cnt, string name, bool hidden = false);
|
||||||
|
|
|
||||||
|
|
@ -685,7 +685,8 @@ class Session : public PBD::StatefulDestructible
|
||||||
/* playlist management */
|
/* playlist management */
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> playlist_by_name (string name);
|
boost::shared_ptr<Playlist> playlist_by_name (string name);
|
||||||
void add_playlist (boost::shared_ptr<Playlist>);
|
void unassigned_playlists (std::list<boost::shared_ptr<Playlist> > & list);
|
||||||
|
void add_playlist (boost::shared_ptr<Playlist>, bool unused = false);
|
||||||
sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistAdded;
|
sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistAdded;
|
||||||
sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistRemoved;
|
sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistRemoved;
|
||||||
|
|
||||||
|
|
|
||||||
60
libs/ardour/ardour/tempo_map_importer.h
Normal file
60
libs/ardour/ardour/tempo_map_importer.h
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_tempo_map_importer_h__
|
||||||
|
#define __ardour_tempo_map_importer_h__
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
#include <ardour/tempo.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class TempoMapImportHandler : public ElementImportHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TempoMapImportHandler (XMLTree const & source, Session & session);
|
||||||
|
string get_info () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TempoMapImporter : public ElementImporter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::shared_ptr<XMLNode> XMLNodePtr;
|
||||||
|
public:
|
||||||
|
TempoMapImporter (XMLTree const & source, Session & session, XMLNode const & node);
|
||||||
|
|
||||||
|
virtual string get_info () const;
|
||||||
|
virtual bool prepare_move ();
|
||||||
|
virtual void cancel_move ();
|
||||||
|
virtual void move ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
XMLNode xml_tempo_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif
|
||||||
221
libs/ardour/audio_playlist_importer.cc
Normal file
221
libs/ardour/audio_playlist_importer.cc
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/audio_playlist_importer.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
#include <pbd/compose.h>
|
||||||
|
#include <pbd/error.h>
|
||||||
|
|
||||||
|
#include <ardour/audio_region_importer.h>
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/playlist.h>
|
||||||
|
#include <ardour/playlist_factory.h>
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
/**** Handler ***/
|
||||||
|
AudioPlaylistImportHandler::AudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler, const char * nodename) :
|
||||||
|
ElementImportHandler (source, session),
|
||||||
|
region_handler (region_handler)
|
||||||
|
{
|
||||||
|
XMLNode const * root = source.root();
|
||||||
|
XMLNode const * playlists;
|
||||||
|
|
||||||
|
if (!(playlists = root->child (nodename))) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNodeList const & pl_children = playlists->children();
|
||||||
|
for (XMLNodeList::const_iterator it = pl_children.begin(); it != pl_children.end(); ++it) {
|
||||||
|
const XMLProperty* type = (*it)->property("type");
|
||||||
|
if ( !type || type->value() == "audio" ) {
|
||||||
|
try {
|
||||||
|
elements.push_back (ElementPtr ( new AudioPlaylistImporter (source, session, *this, **it)));
|
||||||
|
} catch (failed_constructor err) {
|
||||||
|
set_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
AudioPlaylistImportHandler::get_info () const
|
||||||
|
{
|
||||||
|
return _("Audio Playlists");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPlaylistImportHandler::get_regions (XMLNode const & node, ElementList & list)
|
||||||
|
{
|
||||||
|
region_handler.create_regions_from_children (node, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPlaylistImportHandler::update_region_id (XMLProperty* id_prop)
|
||||||
|
{
|
||||||
|
PBD::ID old_id (id_prop->value());
|
||||||
|
PBD::ID new_id (region_handler.get_new_id (old_id));
|
||||||
|
id_prop->set_value (new_id.to_s());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** AudioPlaylistImporter ***/
|
||||||
|
AudioPlaylistImporter::AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node) :
|
||||||
|
ElementImporter (source, session),
|
||||||
|
handler (handler),
|
||||||
|
xml_playlist (node),
|
||||||
|
diskstream_id ("0")
|
||||||
|
{
|
||||||
|
bool ds_ok = false;
|
||||||
|
|
||||||
|
// Populate region list
|
||||||
|
ElementImportHandler::ElementList elements;
|
||||||
|
handler.get_regions (node, elements);
|
||||||
|
for (ElementImportHandler::ElementList::iterator it = elements.begin(); it != elements.end(); ++it) {
|
||||||
|
regions.push_back (boost::dynamic_pointer_cast<AudioRegionImporter> (*it));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse XML
|
||||||
|
XMLPropertyList const & props = xml_playlist.properties();
|
||||||
|
for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
|
||||||
|
string prop = (*it)->name();
|
||||||
|
if (!prop.compare("type") || !prop.compare("frozen")) {
|
||||||
|
// All ok
|
||||||
|
} else if (!prop.compare("name")) {
|
||||||
|
name = (*it)->value();
|
||||||
|
} else if (!prop.compare("orig_diskstream_id")) {
|
||||||
|
ds_ok = true;
|
||||||
|
} else {
|
||||||
|
std::cerr << string_compose (X_("AudioPlaylistImporter did not recognise XML-property \"%1\""), prop) << endmsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ds_ok) {
|
||||||
|
error << string_compose (X_("AudioPlaylistImporter (%1): did not find XML-property \"orig_diskstream_id\" which is mandatory"), name) << endmsg;
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
AudioPlaylistImporter::get_info () const
|
||||||
|
{
|
||||||
|
XMLNodeList children = xml_playlist.children();
|
||||||
|
unsigned int regions = 0;
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
for (XMLNodeIterator it = children.begin(); it != children.end(); it++) {
|
||||||
|
if ((*it)->name() == "Region") {
|
||||||
|
++regions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << regions << " ";
|
||||||
|
|
||||||
|
if (regions == 1) {
|
||||||
|
oss << _("region");
|
||||||
|
} else {
|
||||||
|
oss << _("regions");
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioPlaylistImporter::prepare_move ()
|
||||||
|
{
|
||||||
|
// Rename
|
||||||
|
while (session.playlist_by_name (name) || !handler.check_name (name)) {
|
||||||
|
std::pair<bool, string> rename_pair = Rename (_("A playlist with this name already exists, please rename it."), name);
|
||||||
|
if (!rename_pair.first) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name = rename_pair.second;
|
||||||
|
}
|
||||||
|
xml_playlist.property ("name")->set_value (name);
|
||||||
|
handler.add_name (name);
|
||||||
|
|
||||||
|
queued = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPlaylistImporter::cancel_move ()
|
||||||
|
{
|
||||||
|
handler.remove_name (name);
|
||||||
|
queued = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPlaylistImporter::move ()
|
||||||
|
{
|
||||||
|
boost::shared_ptr<Playlist> playlist;
|
||||||
|
|
||||||
|
// Update diskstream id
|
||||||
|
xml_playlist.property ("orig_diskstream_id")->set_value (diskstream_id.to_s());
|
||||||
|
|
||||||
|
// Update region XML in playlist and prepare sources
|
||||||
|
xml_playlist.remove_nodes("Region");
|
||||||
|
for (RegionList::iterator it = regions.begin(); it != regions.end(); ++it) {
|
||||||
|
xml_playlist.add_child_copy ((*it)->get_xml());
|
||||||
|
(*it)->add_sources_to_session();
|
||||||
|
if ((*it)->broken()) {
|
||||||
|
handler.set_dirty();
|
||||||
|
set_broken();
|
||||||
|
return; // TODO clean up?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update region ids in crossfades
|
||||||
|
XMLNodeList crossfades = xml_playlist.children("Crossfade");
|
||||||
|
for (XMLNodeIterator it = crossfades.begin(); it != crossfades.end(); ++it) {
|
||||||
|
XMLProperty* in = (*it)->property("in");
|
||||||
|
XMLProperty* out = (*it)->property("out");
|
||||||
|
if (!in || !out) {
|
||||||
|
error << string_compose (X_("AudioPlaylistImporter (%1): did not find the \"in\" or \"out\" property from a crossfade"), name) << endmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.update_region_id (in);
|
||||||
|
handler.update_region_id (out);
|
||||||
|
|
||||||
|
// rate convert length and position
|
||||||
|
XMLProperty* length = (*it)->property("length");
|
||||||
|
if (length) {
|
||||||
|
length->set_value (rate_convert_samples (length->value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLProperty* position = (*it)->property("position");
|
||||||
|
if (position) {
|
||||||
|
position->set_value (rate_convert_samples (position->value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create playlist
|
||||||
|
playlist = PlaylistFactory::create (session, xml_playlist, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPlaylistImporter::set_diskstream (PBD::ID const & id)
|
||||||
|
{
|
||||||
|
diskstream_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
398
libs/ardour/audio_region_importer.cc
Normal file
398
libs/ardour/audio_region_importer.cc
Normal file
|
|
@ -0,0 +1,398 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/audio_region_importer.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
#include <pbd/compose.h>
|
||||||
|
#include <pbd/error.h>
|
||||||
|
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/region.h>
|
||||||
|
#include <ardour/source_factory.h>
|
||||||
|
#include <ardour/region_factory.h>
|
||||||
|
#include <ardour/session_directory.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
/**** Handler ***/
|
||||||
|
AudioRegionImportHandler::AudioRegionImportHandler (XMLTree const & source, Session & session) :
|
||||||
|
ElementImportHandler (source, session)
|
||||||
|
{
|
||||||
|
XMLNode const * root = source.root();
|
||||||
|
XMLNode const * regions;
|
||||||
|
|
||||||
|
if (!(regions = root->child (X_("Regions")))) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
create_regions_from_children (*regions, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImportHandler::create_regions_from_children (XMLNode const & node, ElementList & list)
|
||||||
|
{
|
||||||
|
XMLNodeList const & children = node.children();
|
||||||
|
for (XMLNodeList::const_iterator it = children.begin(); it != children.end(); ++it) {
|
||||||
|
XMLProperty const * type = (*it)->property("type");
|
||||||
|
if (!(*it)->name().compare ("Region") && (!type || type->value() == "audio") ) {
|
||||||
|
try {
|
||||||
|
list.push_back (ElementPtr ( new AudioRegionImporter (source, session, *this, **it)));
|
||||||
|
} catch (failed_constructor err) {
|
||||||
|
set_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
AudioRegionImportHandler::get_info () const
|
||||||
|
{
|
||||||
|
return _("Audio Regions");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioRegionImportHandler::check_source (string const & filename) const
|
||||||
|
{
|
||||||
|
return (sources.find (filename) != sources.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImportHandler::add_source (string const & filename, boost::shared_ptr<Source> const & source)
|
||||||
|
{
|
||||||
|
sources.insert (SourcePair (filename, source));
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<Source> const &
|
||||||
|
AudioRegionImportHandler::get_source (string const & filename) const
|
||||||
|
{
|
||||||
|
return (sources.find (filename))->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImportHandler::register_id (PBD::ID & old_id, PBD::ID & new_id)
|
||||||
|
{
|
||||||
|
id_map.insert (IdPair (old_id, new_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
PBD::ID const &
|
||||||
|
AudioRegionImportHandler::get_new_id (PBD::ID & old_id) const
|
||||||
|
{
|
||||||
|
return (id_map.find (old_id))->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** AudioRegionImporter ***/
|
||||||
|
AudioRegionImporter::AudioRegionImporter (XMLTree const & source, Session & session, AudioRegionImportHandler & handler, XMLNode const & node) :
|
||||||
|
ElementImporter (source, session),
|
||||||
|
xml_region (node),
|
||||||
|
handler (handler),
|
||||||
|
old_id ("0"),
|
||||||
|
region_prepared (false),
|
||||||
|
sources_prepared (false)
|
||||||
|
{
|
||||||
|
if (!parse_xml_region () || !parse_source_xml ()) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
handler.register_id (old_id, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
AudioRegionImporter::get_info () const
|
||||||
|
{
|
||||||
|
nframes_t length, position;
|
||||||
|
SMPTE::Time length_time, position_time;
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
// Get sample positions
|
||||||
|
std::istringstream iss_length(xml_region.property ("length")->value());
|
||||||
|
iss_length >> length;
|
||||||
|
std::istringstream iss_position(xml_region.property ("position")->value());
|
||||||
|
iss_position >> position;
|
||||||
|
|
||||||
|
// Convert to smpte
|
||||||
|
session.sample_to_smpte(length, length_time, true, false);
|
||||||
|
session.sample_to_smpte(position, position_time, true, false);
|
||||||
|
|
||||||
|
// return info
|
||||||
|
oss << _("Length: ") <<
|
||||||
|
smpte_to_string(length_time) <<
|
||||||
|
_("\nPosition: ") <<
|
||||||
|
smpte_to_string(position_time) <<
|
||||||
|
_("\nChannels: ") <<
|
||||||
|
xml_region.property ("channels")->value();
|
||||||
|
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioRegionImporter::prepare_move ()
|
||||||
|
{
|
||||||
|
queued = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImporter::cancel_move ()
|
||||||
|
{
|
||||||
|
queued = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImporter::move ()
|
||||||
|
{
|
||||||
|
if (!region_prepared) {
|
||||||
|
prepare_region();
|
||||||
|
if (!region_prepared) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (broken()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.add_regions (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioRegionImporter::parse_xml_region ()
|
||||||
|
{
|
||||||
|
XMLPropertyList const & props = xml_region.properties();;
|
||||||
|
bool id_ok = false;
|
||||||
|
bool name_ok = false;
|
||||||
|
|
||||||
|
for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
|
||||||
|
string prop = (*it)->name();
|
||||||
|
if (!prop.compare ("type") || !prop.compare ("stretch") ||
|
||||||
|
!prop.compare ("shift") || !prop.compare ("first_edit") ||
|
||||||
|
!prop.compare ("layer") || !prop.compare ("flags") ||
|
||||||
|
!prop.compare ("scale-gain") || !prop.compare("channels") ||
|
||||||
|
prop.find ("master-source-") == 0 || prop.find ("source-") == 0) {
|
||||||
|
// All ok
|
||||||
|
} else if (!prop.compare ("start") || !prop.compare ("length") ||
|
||||||
|
!prop.compare ("position") || !prop.compare ("ancestral-start") ||
|
||||||
|
!prop.compare ("ancestral-length") || !prop.compare ("sync-position")) {
|
||||||
|
// Sample rate conversion
|
||||||
|
(*it)->set_value (rate_convert_samples ((*it)->value()));
|
||||||
|
} else if (!prop.compare("id")) {
|
||||||
|
// get old id and update id
|
||||||
|
old_id = (*it)->value();
|
||||||
|
(*it)->set_value (id.to_s());
|
||||||
|
id_ok = true;
|
||||||
|
} else if (!prop.compare("name")) {
|
||||||
|
// rename region if necessary
|
||||||
|
name = (*it)->value();
|
||||||
|
name = session.new_region_name (name);
|
||||||
|
(*it)->set_value (name);
|
||||||
|
name_ok = true;
|
||||||
|
} else {
|
||||||
|
std::cerr << string_compose (X_("AudioRegionImporter (%1): did not recognise XML-property \"%1\""), name, prop) << endmsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id_ok) {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"id\""), name) << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name_ok) {
|
||||||
|
error << X_("AudioRegionImporter: did not find necessary XML-property \"name\"") << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioRegionImporter::parse_source_xml ()
|
||||||
|
{
|
||||||
|
uint32_t channels;
|
||||||
|
char buf[128];
|
||||||
|
PBD::sys::path source_dir = get_sound_dir (source);
|
||||||
|
PBD::sys::path source_path;
|
||||||
|
XMLNode * source_node;
|
||||||
|
XMLProperty *prop;
|
||||||
|
|
||||||
|
// Get XML for sources
|
||||||
|
if (!(source_node = source.root()->child (X_("Sources")))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
XMLNodeList const & sources = source_node->children();
|
||||||
|
|
||||||
|
// Get source for each channel
|
||||||
|
if (!(prop = xml_region.property ("channels"))) {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"channels\""), name) << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
channels = atoi (prop->value());
|
||||||
|
for (uint32_t i = 0; i < channels; ++i) {
|
||||||
|
bool source_found = false;
|
||||||
|
|
||||||
|
// Get id for source-n
|
||||||
|
snprintf (buf, sizeof(buf), X_("source-%d"), i);
|
||||||
|
prop = xml_region.property (buf);
|
||||||
|
if (!prop) {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"%3\""), name, buf) << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string source_id = prop->value();
|
||||||
|
|
||||||
|
// Get source
|
||||||
|
for (XMLNodeList::const_iterator it = sources.begin(); it != sources.end(); it++) {
|
||||||
|
prop = (*it)->property ("id");
|
||||||
|
if (prop && !source_id.compare (prop->value())) {
|
||||||
|
source_path = source_dir;
|
||||||
|
prop = (*it)->property ("name");
|
||||||
|
if (!prop) {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): source %2 has no \"name\" property"), name, source_id) << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
source_path /= prop->value();
|
||||||
|
filenames.push_back (source_path.to_string());
|
||||||
|
|
||||||
|
source_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!source_found) {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): could not find all necessary sources"), name) << endmsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBD::sys::path
|
||||||
|
AudioRegionImporter::get_sound_dir (XMLTree const & tree)
|
||||||
|
{
|
||||||
|
PBD::sys::path source_dir = tree.filename();
|
||||||
|
source_dir = source_dir.branch_path();
|
||||||
|
SessionDirectory session_dir(source_dir);
|
||||||
|
source_dir = session_dir.sound_path();
|
||||||
|
|
||||||
|
return source_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImporter::prepare_region ()
|
||||||
|
{
|
||||||
|
if (region_prepared) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceList source_list;
|
||||||
|
prepare_sources();
|
||||||
|
|
||||||
|
// Create source list
|
||||||
|
for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) {
|
||||||
|
source_list.push_back (handler.get_source (*it));
|
||||||
|
}
|
||||||
|
|
||||||
|
// create region and update XML
|
||||||
|
region.push_back (RegionFactory::create (source_list, xml_region));
|
||||||
|
if (*region.begin()) {
|
||||||
|
xml_region = (*region.begin())->get_state();
|
||||||
|
} else {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): could not construct Region"), name) << endmsg;
|
||||||
|
handler.set_errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
region_prepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImporter::prepare_sources ()
|
||||||
|
{
|
||||||
|
if (sources_prepared) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::import_status status;
|
||||||
|
|
||||||
|
// Get sources that still need to be imported
|
||||||
|
for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) {
|
||||||
|
if (!handler.check_source (*it)) {
|
||||||
|
status.paths.push_back (*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare rest of import struct TODO quality
|
||||||
|
status.replace_existing_source = false;
|
||||||
|
status.done = false;
|
||||||
|
status.cancel = false;
|
||||||
|
status.freeze = false;
|
||||||
|
status.progress = 0.0;
|
||||||
|
status.quality = SrcBest;
|
||||||
|
|
||||||
|
// import files
|
||||||
|
// TODO: threading & exception handling
|
||||||
|
session.import_audiofiles (status);
|
||||||
|
|
||||||
|
// Add imported sources to handlers map
|
||||||
|
std::vector<Glib::ustring>::iterator file_it = status.paths.begin();
|
||||||
|
for (SourceList::iterator source_it = status.sources.begin(); source_it != status.sources.end(); ++source_it) {
|
||||||
|
if (*source_it) {
|
||||||
|
handler.add_source(*file_it, *source_it);
|
||||||
|
} else {
|
||||||
|
error << string_compose (X_("AudioRegionImporter (%1): could not import all necessary sources"), name) << endmsg;
|
||||||
|
handler.set_errors();
|
||||||
|
set_broken();
|
||||||
|
}
|
||||||
|
|
||||||
|
++file_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
sources_prepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionImporter::add_sources_to_session ()
|
||||||
|
{
|
||||||
|
if (!sources_prepared) {
|
||||||
|
prepare_sources();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (broken()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) {
|
||||||
|
session.add_source (handler.get_source (*it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode const &
|
||||||
|
AudioRegionImporter::get_xml ()
|
||||||
|
{
|
||||||
|
if(!region_prepared) {
|
||||||
|
prepare_region();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xml_region;
|
||||||
|
}
|
||||||
55
libs/ardour/element_import_handler.cc
Normal file
55
libs/ardour/element_import_handler.cc
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/element_import_handler.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
bool ElementImportHandler::_dirty = false;
|
||||||
|
bool ElementImportHandler::_errors = false;
|
||||||
|
|
||||||
|
ElementImportHandler::~ElementImportHandler ()
|
||||||
|
{
|
||||||
|
_dirty = false;
|
||||||
|
_errors = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ElementImportHandler::check_name (const string & name) const
|
||||||
|
{
|
||||||
|
return std::find (names.begin(), names.end(), name) == names.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ElementImportHandler::add_name (string name)
|
||||||
|
{
|
||||||
|
names.push_back (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ElementImportHandler::remove_name (const string & name)
|
||||||
|
{
|
||||||
|
std::list<string>::iterator it = std::find (names.begin(), names.end(), name);
|
||||||
|
if (it != names.end()) {
|
||||||
|
names.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
libs/ardour/element_importer.cc
Normal file
84
libs/ardour/element_importer.cc
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/element_importer.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include <pbd/convert.h>
|
||||||
|
#include <ardour/session.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
sigc::signal <std::pair<bool, string>, string, string> ElementImporter::Rename;
|
||||||
|
sigc::signal <bool, string> ElementImporter::Prompt;
|
||||||
|
|
||||||
|
ElementImporter::ElementImporter (XMLTree const & source, ARDOUR::Session & session) :
|
||||||
|
source (source),
|
||||||
|
session(session),
|
||||||
|
queued (false),
|
||||||
|
_broken (false)
|
||||||
|
{
|
||||||
|
// Get samplerate
|
||||||
|
XMLProperty *prop;
|
||||||
|
prop = source.root()->property ("sample-rate");
|
||||||
|
if (prop) {
|
||||||
|
std::istringstream iss (prop->value());
|
||||||
|
iss >> sample_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
ElementImporter::smpte_to_string(SMPTE::Time & time) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::setfill('0') << std::right <<
|
||||||
|
std::setw(2) <<
|
||||||
|
time.hours << ":" <<
|
||||||
|
std::setw(2) <<
|
||||||
|
time.minutes << ":" <<
|
||||||
|
std::setw(2) <<
|
||||||
|
time.seconds << ":" <<
|
||||||
|
std::setw(2) <<
|
||||||
|
time.frames;
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
nframes_t
|
||||||
|
ElementImporter::rate_convert_samples (nframes_t samples) const
|
||||||
|
{
|
||||||
|
if (sample_rate == session.frame_rate()) {
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
// +0.5 for proper rounding
|
||||||
|
return static_cast<nframes_t> (samples * (static_cast<double> (session.nominal_frame_rate()) / sample_rate) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
ElementImporter::rate_convert_samples (string const & samples) const
|
||||||
|
{
|
||||||
|
return to_string (rate_convert_samples (atoi (samples)), std::dec);
|
||||||
|
}
|
||||||
|
|
@ -246,6 +246,14 @@ Location::set_is_start (bool yn, void *src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Location::set_is_range_marker (bool yn, void *src)
|
||||||
|
{
|
||||||
|
if (set_flag_internal (yn, IsRangeMarker)) {
|
||||||
|
FlagsChanged (this, src); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Location::set_auto_punch (bool yn, void *src)
|
Location::set_auto_punch (bool yn, void *src)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
195
libs/ardour/location_importer.cc
Normal file
195
libs/ardour/location_importer.cc
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/location_importer.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <pbd/convert.h>
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
/**** Handler ***/
|
||||||
|
LocationImportHandler::LocationImportHandler (XMLTree const & source, Session & session) :
|
||||||
|
ElementImportHandler (source, session)
|
||||||
|
{
|
||||||
|
XMLNode const *root = source.root();
|
||||||
|
XMLNode const * location_node;
|
||||||
|
|
||||||
|
if (!(location_node = root->child ("Locations"))) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct importable locations
|
||||||
|
XMLNodeList const & locations = location_node->children();
|
||||||
|
for (XMLNodeList::const_iterator it = locations.begin(); it != locations.end(); it++) {
|
||||||
|
try {
|
||||||
|
elements.push_back (ElementPtr ( new LocationImporter (source, session, *this, **it)));
|
||||||
|
} catch (failed_constructor err) {
|
||||||
|
_dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
LocationImportHandler::get_info () const
|
||||||
|
{
|
||||||
|
return _("Locations");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** LocationImporter ***/
|
||||||
|
LocationImporter::LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node) :
|
||||||
|
ElementImporter (source, session),
|
||||||
|
handler (handler),
|
||||||
|
xml_location (node),
|
||||||
|
location (0)
|
||||||
|
{
|
||||||
|
// Parse XML
|
||||||
|
bool name_ok = false;
|
||||||
|
XMLPropertyList props = xml_location.properties();
|
||||||
|
|
||||||
|
for (XMLPropertyIterator it = props.begin(); it != props.end(); ++it) {
|
||||||
|
string prop = (*it)->name();
|
||||||
|
if (!prop.compare ("id") || !prop.compare ("flags") || !prop.compare ("locked")) {
|
||||||
|
// All ok
|
||||||
|
} else if (!prop.compare ("start") || !prop.compare ("end")) {
|
||||||
|
// Sample rate conversion
|
||||||
|
(*it)->set_value (rate_convert_samples ((*it)->value()));
|
||||||
|
} else if (!prop.compare ("name")) {
|
||||||
|
// rename region if necessary
|
||||||
|
name = (*it)->value();
|
||||||
|
name_ok = true;
|
||||||
|
} else {
|
||||||
|
std::cerr << string_compose (X_("LocationImporter did not recognise XML-property \"%1\""), prop) << endmsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name_ok) {
|
||||||
|
error << X_("LocationImporter did not find necessary XML-property \"name\"") << endmsg;
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationImporter::~LocationImporter ()
|
||||||
|
{
|
||||||
|
if (!queued && location) {
|
||||||
|
delete location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
LocationImporter::get_info () const
|
||||||
|
{
|
||||||
|
nframes_t start, end;
|
||||||
|
SMPTE::Time start_time, end_time;
|
||||||
|
|
||||||
|
// Get sample positions
|
||||||
|
std::istringstream iss_start (xml_location.property ("start")->value());
|
||||||
|
iss_start >> start;
|
||||||
|
std::istringstream iss_end (xml_location.property ("end")->value());
|
||||||
|
iss_end >> end;
|
||||||
|
|
||||||
|
// Convert to smpte
|
||||||
|
session.sample_to_smpte (start, start_time, true, false);
|
||||||
|
session.sample_to_smpte (end, end_time, true, false);
|
||||||
|
|
||||||
|
// return info
|
||||||
|
std::ostringstream oss;
|
||||||
|
if (start == end) {
|
||||||
|
oss << _("Location: ") << smpte_to_string (start_time);
|
||||||
|
} else {
|
||||||
|
oss << _("Range\nstart: ") << smpte_to_string (start_time) <<
|
||||||
|
_("\nend: ") << smpte_to_string (end_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LocationImporter::prepare_move ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Location const original (xml_location);
|
||||||
|
location = new Location (original); // Updates id
|
||||||
|
} catch (failed_constructor& err) {
|
||||||
|
throw std::runtime_error (X_("Error in session file!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, string> rename_pair;
|
||||||
|
|
||||||
|
if (location->is_auto_punch()) {
|
||||||
|
rename_pair = Rename (_("The location is the Punch range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
|
||||||
|
if (!rename_pair.first) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = rename_pair.second;
|
||||||
|
location->set_auto_punch (false, this);
|
||||||
|
location->set_is_range_marker (true, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location->is_auto_loop()) {
|
||||||
|
rename_pair = Rename (_("The location is a Loop range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
|
||||||
|
if (!rename_pair.first) { return false; }
|
||||||
|
|
||||||
|
location->set_auto_loop (false, this);
|
||||||
|
location->set_is_range_marker (true, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// duplicate name checking
|
||||||
|
Locations::LocationList const & locations(session.locations()->list());
|
||||||
|
for (Locations::LocationList::const_iterator it = locations.begin(); it != locations.end(); ++it) {
|
||||||
|
if (!((*it)->name().compare (location->name())) || !handler.check_name (location->name())) {
|
||||||
|
rename_pair = Rename (_("A location with that name already exists.\nYou may rename the imported location:"), name);
|
||||||
|
if (!rename_pair.first) { return false; }
|
||||||
|
name = rename_pair.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location->set_name (name);
|
||||||
|
queued = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LocationImporter::cancel_move ()
|
||||||
|
{
|
||||||
|
queued = false;
|
||||||
|
if (location) {
|
||||||
|
delete location;
|
||||||
|
location = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LocationImporter::move ()
|
||||||
|
{
|
||||||
|
if (!queued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
session.locations()->add (location);
|
||||||
|
}
|
||||||
|
|
@ -29,10 +29,10 @@
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistFactory::PlaylistCreated;
|
sigc::signal<void,boost::shared_ptr<Playlist>, bool> PlaylistFactory::PlaylistCreated;
|
||||||
|
|
||||||
boost::shared_ptr<Playlist>
|
boost::shared_ptr<Playlist>
|
||||||
PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden)
|
PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden, bool unused)
|
||||||
{
|
{
|
||||||
const XMLProperty* type = node.property("type");
|
const XMLProperty* type = node.property("type");
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden)
|
||||||
pl->set_region_ownership ();
|
pl->set_region_ownership ();
|
||||||
|
|
||||||
if (pl && !hidden) {
|
if (pl && !hidden) {
|
||||||
PlaylistCreated (pl);
|
PlaylistCreated (pl, unused);
|
||||||
}
|
}
|
||||||
return pl;
|
return pl;
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ PlaylistFactory::create (DataType type, Session& s, string name, bool hidden)
|
||||||
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, name, hidden));
|
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, name, hidden));
|
||||||
|
|
||||||
if (pl && !hidden) {
|
if (pl && !hidden) {
|
||||||
PlaylistCreated (pl);
|
PlaylistCreated (pl, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
|
|
@ -84,7 +84,7 @@ PlaylistFactory::create (boost::shared_ptr<const Playlist> old, string name, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pl && !hidden) {
|
if (pl && !hidden) {
|
||||||
PlaylistCreated (pl);
|
PlaylistCreated (pl, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
|
|
|
||||||
|
|
@ -3368,7 +3368,23 @@ Session::playlist_by_name (string name)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::add_playlist (boost::shared_ptr<Playlist> playlist)
|
Session::unassigned_playlists (std::list<boost::shared_ptr<Playlist> > & list)
|
||||||
|
{
|
||||||
|
Glib::Mutex::Lock lm (playlist_lock);
|
||||||
|
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
|
||||||
|
if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) {
|
||||||
|
list.push_back (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
|
||||||
|
if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) {
|
||||||
|
list.push_back (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
|
||||||
{
|
{
|
||||||
if (playlist->hidden()) {
|
if (playlist->hidden()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -3383,6 +3399,10 @@ Session::add_playlist (boost::shared_ptr<Playlist> playlist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unused) {
|
||||||
|
playlist->release();
|
||||||
|
}
|
||||||
|
|
||||||
set_dirty();
|
set_dirty();
|
||||||
|
|
||||||
PlaylistAdded (playlist); /* EMIT SIGNAL */
|
PlaylistAdded (playlist); /* EMIT SIGNAL */
|
||||||
|
|
|
||||||
108
libs/ardour/tempo_map_importer.cc
Normal file
108
libs/ardour/tempo_map_importer.cc
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
Author: Sakari Bergen
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/tempo_map_importer.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
#include <pbd/compose.h>
|
||||||
|
#include <pbd/error.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
/**** Handler ***/
|
||||||
|
TempoMapImportHandler::TempoMapImportHandler (XMLTree const & source, Session & session) :
|
||||||
|
ElementImportHandler (source, session)
|
||||||
|
{
|
||||||
|
XMLNode const * root = source.root();
|
||||||
|
XMLNode const * tempo_map;
|
||||||
|
|
||||||
|
if (!(tempo_map = root->child (X_("TempoMap")))) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.push_back (ElementPtr ( new TempoMapImporter (source, session, *tempo_map)));
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
TempoMapImportHandler::get_info () const
|
||||||
|
{
|
||||||
|
return _("Tempo map");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** TempoMapImporter ***/
|
||||||
|
TempoMapImporter::TempoMapImporter (XMLTree const & source, Session & session, XMLNode const & node) :
|
||||||
|
ElementImporter (source, session),
|
||||||
|
xml_tempo_map (node)
|
||||||
|
{
|
||||||
|
name = _("Tempo Map");
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
TempoMapImporter::get_info () const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
unsigned int tempos = 0;
|
||||||
|
unsigned int meters = 0;
|
||||||
|
XMLNodeList children = xml_tempo_map.children();
|
||||||
|
|
||||||
|
for (XMLNodeIterator it = children.begin(); it != children.end(); it++) {
|
||||||
|
if ((*it)->name() == "Tempo") {
|
||||||
|
tempos++;
|
||||||
|
} else if ((*it)->name() == "Meters") {
|
||||||
|
meters++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return info
|
||||||
|
oss << _("Tempo marks: ") << tempos << _("\nMeter marks: ") << meters;
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TempoMapImporter::prepare_move ()
|
||||||
|
{
|
||||||
|
// Prompt user for verification
|
||||||
|
bool replace = Prompt (_("This will replace the current tempo map!\nAre you shure you want to do this?"));
|
||||||
|
|
||||||
|
if (replace) {
|
||||||
|
queued = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TempoMapImporter::cancel_move ()
|
||||||
|
{
|
||||||
|
queued = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TempoMapImporter::move ()
|
||||||
|
{
|
||||||
|
session.tempo_map().set_state (xml_tempo_map);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue