Merged with trunk R920.

git-svn-id: svn://localhost/ardour2/branches/midi@921 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2006-09-19 03:29:16 +00:00
parent c7307c09b8
commit 7bd41538d9
91 changed files with 3496 additions and 867 deletions

View File

@ -468,17 +468,6 @@ if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0:
libraries['boost'] = conf.Finish ()
conf = env.Configure ()
# jack_port_ensure_monitor available
if conf.CheckFunc('jack_port_ensure_monitor'):
env.Append(CCFLAGS='-DWITH_JACK_PORT_ENSURE_MONITOR')
else:
print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
env = conf.Finish()
#
# Check for liblo

View File

@ -73,13 +73,13 @@ ActionManager::init ()
ui_manager->add_ui_from_file (ui_file);
loaded = true;
} catch (Glib::MarkupError& err) {
error << "badly formatted UI definition file" << endmsg;
error << _("badly formatted UI definition file") << endmsg;
} catch (...) {
error << "Ardour menu definition file not found" << endmsg;
error << _("Ardour menu definition file not found") << endmsg;
}
if (!loaded) {
error << "ardour will not work without a valid ardour.menus file" << endmsg;
error << _("ardour will not work without a valid ardour.menus file") << endmsg;
exit(1);
}
}
@ -277,7 +277,7 @@ ActionManager::uncheck_toggleaction (const char * name)
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
tact->set_active (false);
} else {
error << "Unknown action name: " << name << endmsg;
error << string_compose (_("Unknown action name: %1"), name) << endmsg;
}
delete [] group_name;

View File

@ -1,3 +1,3 @@
#!/bin/sh
source `dirname "$0"`/ardev_common.sh
exec gtk2_ardour/ardour.bin --novst "$*"
exec gtk2_ardour/ardour.bin --novst $*

View File

@ -214,6 +214,30 @@
<menuitem action='FileHeaderFormatCAF'/>
</menu>
</menu>
<menu action='SMPTE'>
<menuitem action='Smpte23976'/>
<menuitem action='Smpte24'/>
<menuitem action='Smpte24976'/>
<menuitem action='Smpte25'/>
<menuitem action='Smpte2997drop'/>
<menuitem action='Smpte2997'/>
<menuitem action='Smpte30drop'/>
<menuitem action='Smpte30'/>
<menuitem action='Smpte5994'/>
<menuitem action='Smpte60'/>
</menu>
<menu action='Pullup'>
<menuitem action='PullupPlus4Plus1'/>
<menuitem action='PullupPlus4'/>
<menuitem action='PullupPlus4Minus1'/>
<menuitem action='PullupPlus1'/>
<menuitem action='PullupNone'/>
<menuitem action='PullupMinus1'/>
<menuitem action='PullupMinus4Plus1'/>
<menuitem action='PullupMinus4'/>
<menuitem action='PullupMinus4Minus1'/>
</menu>
<separator/>
<menu action='Autoconnect'>
<menuitem action='AutoConnectNewTrackInputsToHardware'/>
<separator/>

View File

@ -1651,6 +1651,9 @@ ARDOUR_UI::save_template ()
void
ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
{
string session_name;
string session_path;
int response = Gtk::RESPONSE_NONE;
new_session_dialog->set_modal(true);
@ -1672,14 +1675,28 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
new_session_dialog->reset();
} else if (response == Gtk::RESPONSE_YES) {
/* YES == OPEN, but there's no enum for that */
std::string session_name = new_session_dialog->session_name();
std::string session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
session_name = new_session_dialog->session_name();
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
cerr << "session name is empty\n";
continue;
}
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
load_session (Glib::path_get_dirname (session_name), session_name);
} else {
session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
}
} else if (response == Gtk::RESPONSE_OK) {
if (new_session_dialog->get_current_page() == 1) {
/* XXX this is a bit of a hack..
@ -1687,93 +1704,121 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
if we're on page 1 (the load page)
Unfortunately i can't see how atm..
*/
std::string session_name = new_session_dialog->session_name();
std::string session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
cerr << "session name is empty 2\n";
continue;
}
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
load_session (Glib::path_get_dirname (session_name), session_name);
} else {
session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
}
} else {
_session_is_new = true;
std::string session_name = new_session_dialog->session_name();
std::string session_path = new_session_dialog->session_folder();
session_name = new_session_dialog->session_name();
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
cerr << "session name is empty 3\n";
continue;
}
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
} else {
std::string session_path = new_session_dialog->session_folder();
}
//XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point.
session_path = Glib::build_filename(session_path, session_name);
session_path = Glib::build_filename (session_path, session_name);
std::string template_name = new_session_dialog->session_template_name();
if (new_session_dialog->use_session_template()) {
load_session (session_path, session_name, &template_name);
load_session (session_path, session_name, &template_name);
} else {
uint32_t cchns;
uint32_t cchns;
uint32_t mchns;
Session::AutoConnectOption iconnect;
Session::AutoConnectOption oconnect;
if (new_session_dialog->create_control_bus()) {
cchns = (uint32_t) new_session_dialog->control_channel_count();
cchns = (uint32_t) new_session_dialog->control_channel_count();
} else {
cchns = 0;
cchns = 0;
}
if (new_session_dialog->create_master_bus()) {
mchns = (uint32_t) new_session_dialog->master_channel_count();
mchns = (uint32_t) new_session_dialog->master_channel_count();
} else {
mchns = 0;
mchns = 0;
}
if (new_session_dialog->connect_inputs()) {
iconnect = Session::AutoConnectPhysical;
iconnect = Session::AutoConnectPhysical;
} else {
iconnect = Session::AutoConnectOption (0);
iconnect = Session::AutoConnectOption (0);
}
/// @todo some minor tweaks.
if (new_session_dialog->connect_outs_to_master()) {
oconnect = Session::AutoConnectMaster;
oconnect = Session::AutoConnectMaster;
} else if (new_session_dialog->connect_outs_to_physical()) {
oconnect = Session::AutoConnectPhysical;
oconnect = Session::AutoConnectPhysical;
} else {
oconnect = Session::AutoConnectOption (0);
oconnect = Session::AutoConnectOption (0);
}
uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
build_session (session_path,
session_name,
cchns,
mchns,
iconnect,
oconnect,
nphysin,
nphysout,
engine->frame_rate() * 60 * 5);
session_name,
cchns,
mchns,
iconnect,
oconnect,
nphysin,
nphysout,
engine->frame_rate() * 60 * 5);
}
}
}
}
} while (response == Gtk::RESPONSE_NONE);
show();
new_session_dialog->get_window()->set_cursor();
new_session_dialog->hide();
}
void
ARDOUR_UI::close_session()
{
unload_session();
new_session ();
unload_session();
new_session ();
}
int
@ -1873,6 +1918,11 @@ ARDOUR_UI::show ()
{
if (editor) {
editor->show_window ();
if (!shown_flag) {
editor->present ();
}
shown_flag = true;
}

View File

@ -79,6 +79,10 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
{
editor->connect_to_session (s);
mixer->connect_to_session (s);
/* its safe to do this now */
s->restore_history (s->snap_name());
}
void

View File

@ -131,10 +131,6 @@ ARDOUR_UI::connect_to_session (Session *s)
start_clocking ();
start_blinking ();
if (editor) {
editor->present();
}
transport_stopped ();
second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_second), 1000);

View File

@ -463,6 +463,7 @@ ARDOUR_UI::setup_session_options ()
session_control_changed (Session::AutoReturn);
session_control_changed (Session::AutoInput);
session_control_changed (Session::Clicking);
session_control_changed (Session::SmpteMode);
session->ControlChanged.connect (mem_fun (*this, &ARDOUR_UI::queue_session_control_changed));
}
@ -555,7 +556,6 @@ ARDOUR_UI::session_control_changed (Session::ControlType t)
case Session::CrossfadingModel:
break;
case Session::AutoPlay:
map_some_session_state ("Transport", "ToggleAutoPlay", &Session::get_auto_play);
break;

View File

@ -68,6 +68,7 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
_amplitude_above_axis = 1.0;
use_rec_regions = tv.editor.show_waveforms_recording ();
}
AudioStreamView::~AudioStreamView ()
@ -215,9 +216,7 @@ AudioStreamView::playlist_modified ()
StreamView::playlist_modified();
/* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked
correctly.
*/
/* make sure xfades are on top and all the regionviews are stacked correctly. */
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
(*i)->get_canvas_group()->raise_to_top();
@ -419,10 +418,11 @@ AudioStreamView::setup_rec_box ()
boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion>
(RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false)));
assert(region);
region->set_position (_trackview.session().transport_frame(), this);
rec_regions.push_back (region);
/* catch it if it goes away */
region->GoingAway.connect (bind (mem_fun (*this, &AudioStreamView::remove_rec_region), region));
// rec regions are destroyed in setup_rec_box
/* we add the region later */
}
@ -504,6 +504,14 @@ AudioStreamView::setup_rec_box ()
/* remove temp regions */
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) {
list<boost::shared_ptr<Region> >::iterator tmp;
tmp = iter;
++tmp;
(*iter)->drop_references ();
iter = tmp;
}
rec_regions.clear();
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";
@ -567,9 +575,10 @@ AudioStreamView::update_rec_regions ()
continue;
}
// FIXME
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(*iter);
assert(region);
if (!region) {
continue;
}
jack_nframes_t origlen = region->length();

View File

@ -163,9 +163,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
XMLNode& get_state (void);
int set_state (const XMLNode&);
PBD::ID id() { return _id; }
protected:
PBD::ID _id;
string _name;
guint32 _height;
uint32_t _line_color;

View File

@ -263,7 +263,7 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
GnomeCanvasSimpleRect* simplerect;
double x1, x2, y1, y2;
double old_x1, old_x2, old_y1, old_y2;
double a, b;
double a, b, c, d;
old_x1 = item->x1;
old_y1 = item->y1;
@ -287,42 +287,24 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
/* now queue redraws for changed areas */
if (item->x1 != old_x1) {
/* left edge changed. redraw the area that altered */
a = MIN(item->x1, old_x1);
b = MAX(item->x1, old_x1);
gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
}
if (item->x2 != old_x2) {
/* right edge changed. redraw the area that altered */
a = MIN(item->x2, old_x2);
b = MAX(item->x2, old_x2);
gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
}
if (item->y1 != old_y1) {
/* top edge changed. redraw the area that altered */
a = MIN(item->y1, old_y1);
b = MAX(item->y1, old_y1);
gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
}
if (item->y2 != old_y2) {
/* lower edge changed. redraw the area that altered */
a = MIN(item->y2, old_y2);
b = MAX(item->y2, old_y2);
gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
}
a = MIN(a, item->x2);
a = MIN(a, old_x2);
b = MAX(b, item->x2);
b = MAX(b, old_x2);
c = MIN(item->y1, old_y1);
d = MAX(item->y1, old_y1);
c = MIN(c,item->y2);
c = MIN(c, old_y2);
d = MAX(d,item->y2);
d = MAX(d, old_y2);
gnome_canvas_request_redraw (item->canvas, a, c, b + 0.5, d + 0.5);
}
/*
@ -494,8 +476,8 @@ gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *c
gnome_canvas_request_redraw (item->canvas,
simplerect->bbox_ulx,
simplerect->bbox_uly,
simplerect->bbox_lrx+1,
simplerect->bbox_lry+1);
simplerect->bbox_lrx+0.5,
simplerect->bbox_lry+0.5);
simplerect->full_draw_on_update = FALSE;
}

View File

@ -54,7 +54,8 @@ DISPLAYCONTROL(ShowMeasures)
DISPLAYCONTROL(ShowWaveforms)
DISPLAYCONTROL(ShowWaveformsRecording)
IMPORTMODE(ImportAsRegion)
IMPORTMODE(ImportAsTrack)
IMPORTMODE(ImportAsTapeTrack)
IMPORTMODE(ImportToTrack)
// if this is changed, remember to update the string table in sfdb_ui.cc
IMPORTMODE(ImportAsRegion=0)
IMPORTMODE(ImportToTrack=1)
IMPORTMODE(ImportAsTrack=2)
IMPORTMODE(ImportAsTapeTrack=3)

View File

@ -643,7 +643,7 @@ Editor::Editor (AudioEngine& eng)
edit_pane.pack1 (edit_packer, true, true);
edit_pane.pack2 (the_notebook, false, true);
edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
top_hbox.pack_start (toolbar_frame, true, true);
@ -700,6 +700,7 @@ Editor::Editor (AudioEngine& eng)
ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false));
ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true));
ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
constructed = true;
instant_save ();
@ -882,6 +883,9 @@ Editor::reposition_x_origin (jack_nframes_t frame)
}
horizontal_adjustment.set_value (frame/frames_per_unit);
} else {
update_fixed_rulers();
tempo_map_changed (Change (0));
}
}
@ -965,20 +969,10 @@ void
Editor::canvas_horizontally_scrolled ()
{
Glib::signal_idle().connect (mem_fun(*this, &Editor::lazy_canvas_horizontally_scrolled));
}
bool
Editor::lazy_canvas_horizontally_scrolled ()
{
leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
update_fixed_rulers ();
tempo_map_changed (Change (0));
return false;
}
void
@ -996,7 +990,6 @@ Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
set_frames_per_unit (nfpu);
reposition_x_origin (frame);
repos_zoom_queued = false;
return FALSE;
@ -1033,6 +1026,10 @@ Editor::session_control_changed (Session::ControlType t)
update_layering_model ();
break;
case Session::SmpteMode:
update_smpte_mode ();
break;
default:
break;
}
@ -1179,6 +1176,9 @@ Editor::connect_to_session (Session *t)
session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_smpte_mode)));
session_connections.push_back (session->PullupChanged.connect (mem_fun(*this, &Editor::update_video_pullup)));
session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
edit_groups_changed ();
@ -1266,9 +1266,12 @@ Editor::connect_to_session (Session *t)
}
/* xfade visibility state set from editor::set_state() */
update_crossfade_model ();
update_layering_model ();
update_crossfade_model();
update_layering_model();
update_smpte_mode();
update_video_pullup();
handle_new_duration ();
@ -1292,7 +1295,7 @@ Editor::connect_to_session (Session *t)
horizontal_adjustment.set_value (0);
restore_ruler_visibility ();
tempo_map_changed (Change (0));
//tempo_map_changed (Change (0));
session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
edit_cursor->set_position (0);
@ -1328,6 +1331,7 @@ Editor::connect_to_session (Session *t)
}
/* register for undo history */
session->register_with_memento_command_factory(_id, this);
}
@ -2110,6 +2114,9 @@ Editor::set_state (const XMLNode& node)
int x, y, xoff, yoff;
Gdk::Geometry g;
if ((prop = node.property ("id")) != 0) {
_id = prop->value ();
}
if ((geometry = find_named_node (node, "geometry")) == 0) {
@ -2241,6 +2248,9 @@ Editor::get_state ()
XMLNode* node = new XMLNode ("Editor");
char buf[32];
_id.print (buf);
node->add_property ("id", buf);
if (is_realized()) {
Glib::RefPtr<Gdk::Window> win = get_window();
@ -2250,7 +2260,7 @@ Editor::get_state ()
win->get_size(width, height);
XMLNode* geometry = new XMLNode ("geometry");
char buf[32];
snprintf(buf, sizeof(buf), "%d", width);
geometry->add_property("x_size", string(buf));
snprintf(buf, sizeof(buf), "%d", height);
@ -4085,6 +4095,7 @@ Editor::restore_editing_space ()
{
mouse_mode_tearoff->set_visible (true);
tools_tearoff->set_visible (true);
edit_pane.set_position (pre_maximal_pane_position);
unfullscreen();
@ -4138,6 +4149,87 @@ Editor::on_key_press_event (GdkEventKey* ev)
return key_press_focus_accelerator_handler (*this, ev);
}
void
Editor::update_smpte_mode ()
{
ENSURE_GUI_THREAD(mem_fun(*this, &Editor::update_smpte_mode));
RefPtr<Action> act;
float frames = session->smpte_frames_per_second;
bool drop = session->smpte_drop_frames;
if ((frames < 23.976 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte23976"));
else if ((frames < 24 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte24"));
else if ((frames < 24.976 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte24976"));
else if ((frames < 25 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte25"));
else if ((frames < 29.97 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997"));
else if ((frames < 29.97 * 1.0005) && drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997drop"));
else if ((frames < 30 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte30"));
else if ((frames < 30 * 1.0005) && drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte30drop"));
else if ((frames < 59.94 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte5994"));
else if ((frames < 60 * 1.0005) && !drop)
act = ActionManager::get_action (X_("Editor"), X_("Smpte60"));
else
cerr << "Unexpected SMPTE value (" << frames << (drop ? "drop" : "") << ") in update_smpte_mode. Menu is probably wrong\n" << endl;
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
if (ract && !ract->get_active()) {
ract->set_active (true);
}
}
}
void
Editor::update_video_pullup ()
{
ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_video_pullup));
RefPtr<Action> act;
float pullup = session->video_pullup;
if ( pullup < (-4.1667 - 0.1) * 0.99) {
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Minus1"));
} else if ( pullup < (-4.1667) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4"));
} else if ( pullup < (-4.1667 + 0.1) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Plus1"));
} else if ( pullup < (-0.1) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus1"));
} else if (pullup > (4.1667 + 0.1) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Plus1"));
} else if ( pullup > (4.1667) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4"));
} else if ( pullup > (4.1667 - 0.1) * 0.99) {
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Minus1"));
} else if ( pullup > (0.1) * 0.99 ) {
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus1"));
} else
act = ActionManager::get_action (X_("Editor"), X_("PullupNone"));
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
if (ract && !ract->get_active()) {
ract->set_active (true);
}
}
}
void
Editor::update_layering_model ()
{
@ -4163,7 +4255,6 @@ Editor::update_layering_model ()
}
}
void
Editor::update_crossfade_model ()
{

View File

@ -143,8 +143,6 @@ class Editor : public PublicEditor
XMLNode& get_state ();
int set_state (const XMLNode& );
PBD::ID id() { return _id; }
void set_mouse_mode (Editing::MouseMode, bool force=true);
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () { return mouse_mode; }
@ -231,6 +229,7 @@ class Editor : public PublicEditor
void set_show_measures (bool yn);
bool show_measures () const { return _show_measures; }
bool initial_ruler_update_required;
#ifdef FFT_ANALYSIS
/* analysis window */
@ -302,6 +301,14 @@ class Editor : public PublicEditor
void set_meter_falloff (int);
void set_meter_hold (int32_t);
/* SMPTE timecode & video sync */
void smpte_fps_chosen (ARDOUR::Session::SmpteFormat format);
void video_pullup_chosen (ARDOUR::Session::PullupFormat pullup);
void update_smpte_mode();
void update_video_pullup();
/* xfades */
void toggle_auto_xfade ();
@ -311,8 +318,8 @@ class Editor : public PublicEditor
void update_crossfade_model ();
void set_crossfade_model (ARDOUR::CrossfadeModel);
/* layers */
/* layers */
void set_layer_model (ARDOUR::Session::LayerModel);
void update_layering_model ();
@ -349,8 +356,6 @@ class Editor : public PublicEditor
ARDOUR::AudioEngine& engine;
bool constructed;
PBD::ID _id;
PlaylistSelector* _playlist_selector;
void set_frames_per_unit (double);
@ -683,7 +688,7 @@ class Editor : public PublicEditor
void tie_vertical_scrolling ();
void canvas_horizontally_scrolled ();
bool lazy_canvas_horizontally_scrolled ();
void reposition_and_zoom (jack_nframes_t sample, double fpu);
gint deferred_reposition_and_zoom (jack_nframes_t sample, double fpu);
void end_location_changed (ARDOUR::Location*);
@ -1185,8 +1190,6 @@ class Editor : public PublicEditor
bool _follow_playhead;
bool _show_waveforms_recording;
void add_bbt_marks (ARDOUR::TempoMap::BBTPointList&);
ARDOUR::TempoMap::BBTPointList *current_bbt_points;
typedef vector<ArdourCanvas::SimpleLine*> TimeLineList;
@ -1197,7 +1200,7 @@ class Editor : public PublicEditor
ArdourCanvas::SimpleLine* get_time_line ();
void hide_measures ();
void draw_measures ();
void draw_time_bars ();
bool lazy_hide_and_draw_measures ();
void new_tempo_section ();
@ -1506,7 +1509,7 @@ class Editor : public PublicEditor
jack_nframes_t autoscroll_distance;
static gint _autoscroll_canvas (void *);
gint autoscroll_canvas ();
bool autoscroll_canvas ();
void start_canvas_autoscroll (int direction);
void stop_canvas_autoscroll ();
void maybe_autoscroll (GdkEvent*);

View File

@ -39,6 +39,8 @@ 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_("SMPTE"), _("SMPTE fps"));
ActionManager::register_action (editor_actions, X_("Pullup"), _("Pullup / Pulldown"));
ActionManager::register_action (editor_actions, X_("Metering"), _("Metering"));
ActionManager::register_action (editor_actions, X_("MeteringFallOffRate"), _("Fall off rate"));
ActionManager::register_action (editor_actions, X_("MeteringHoldTime"), _("Hold Time"));
@ -393,6 +395,31 @@ Editor::register_actions ()
ActionManager::register_radio_action (editor_actions, layer_model_group, X_("LayerMoveAddHigher"), _("Most Recently Moved/Added is Higher"), bind (mem_fun (*this, &Editor::set_layer_model), Session::MoveAddHigher));
ActionManager::register_radio_action (editor_actions, layer_model_group, X_("LayerAddHigher"), _("Most Recently Added is Higher"), bind (mem_fun (*this, &Editor::set_layer_model), Session::AddHigher));
RadioAction::Group smpte_group;
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte23976"), _("23.976"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_23976));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte24"), _("24"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_24));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte24976"), _("24.976"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_24976));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte25"), _("25"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_25));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte2997"), _("29.97"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_2997));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte2997drop"), _("29.97 drop"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_2997drop));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte30"), _("30"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_30));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte30drop"), _("30 drop"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_30drop));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte5994"), _("59.94"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_5994));
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte60"), _("60"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_60));
RadioAction::Group pullup_group;
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4Plus1"), _("+4.1667% + 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4Plus1));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4"), _("+4.1667%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4Minus1"), _("+4.1667% - 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4Minus1));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus1"), _("+ 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus1));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupNone"), _("None"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_None));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus1"), _("- 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus1));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4Plus1"), _("-4.1667% + 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4Plus1));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4"), _("-4.1667%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4));
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4Minus1"), _("-4.1667% - 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4Minus1));
ActionManager::add_action_group (rl_actions);
ActionManager::add_action_group (zoom_actions);
ActionManager::add_action_group (mouse_mode_actions);
@ -492,6 +519,150 @@ Editor::set_layer_model (Session::LayerModel model)
}
}
void
Editor::smpte_fps_chosen (Session::SmpteFormat format)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
if (session) {
float fps = 10;
bool drop = false;
RefPtr<Action> act;
switch (format) {
case Session::smpte_23976: {
fps=23.976;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte23976"));
} break;
case Session::smpte_24: {
fps=24;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte24"));
} break;
case Session::smpte_24976: {
fps=24.976;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte24976"));
} break;
case Session::smpte_25: {
fps=25;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte25"));
} break;
case Session::smpte_2997: {
fps=29.97;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997"));
} break;
case Session::smpte_2997drop: {
fps=29.97;
drop = true;
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997drop"));
} break;
case Session::smpte_30: {
fps=30;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte30"));
} break;
case Session::smpte_30drop: {
fps=30;
drop = true;
act = ActionManager::get_action (X_("Editor"), X_("Smpte30drop"));
} break;
case Session::smpte_5994: {
fps=59.94;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte5994"));
} break;
case Session::smpte_60: {
fps=60;
drop = false;
act = ActionManager::get_action (X_("Editor"), X_("Smpte60"));
} break;
default:
cerr << "Editor received unexpected smpte type" << endl;
}
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
if (ract && ract->get_active()) {
session->set_smpte_type (fps, drop);
}
}
}
}
void
Editor::video_pullup_chosen (Session::PullupFormat pullup)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
if (session) {
RefPtr<Action> act;
float pull = 0.0;
switch (pullup) {
case Session::pullup_Plus4Plus1:{
pull = 4.1667 + 0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Plus1"));
} break;
case Session::pullup_Plus4:{
pull = 4.1667;
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4"));
} break;
case Session::pullup_Plus4Minus1:{
pull = 4.1667 - 0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Minus1"));
} break;
case Session::pullup_Plus1:{
pull = 0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus1"));
} break;
case Session::pullup_None:{
pull = 0.0;
act = ActionManager::get_action (X_("Editor"), X_("PullupNone"));
} break;
case Session::pullup_Minus1:{
pull = -0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus1"));
} break;
case Session::pullup_Minus4Plus1:{
pull = -4.1667 + 0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Plus1"));
} break;
case Session::pullup_Minus4:{
pull = -4.1667;
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4"));
} break;
case Session::pullup_Minus4Minus1:{
pull = -4.1667 - 0.1;
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Minus1"));
} break;
default:
cerr << "Session received unexpected pullup type" << endl;
}
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
if (ract && ract->get_active()) {
session->set_video_pullup ( pull );
}
} else cerr << "Editor::video_pullup_chosen could not find action to match pullup." << endl;
}
}
void
Editor::set_crossfade_model (CrossfadeModel model)
{

View File

@ -270,7 +270,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
idspec += string_compose(":%1", n);
try {
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
sources.push_back(source);
}

View File

@ -266,14 +266,15 @@ Editor::initialize_canvas ()
edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event);
playhead_cursor = new Cursor (*this, "red", &Editor::canvas_playhead_cursor_event);
initial_ruler_update_required = true;
track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
}
void
Editor::track_canvas_allocate (Gtk::Allocation alloc)
{
static bool first_time = true;
canvas_width = alloc.get_width();
canvas_height = alloc.get_height();
@ -318,14 +319,16 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
transport_punchout_line->property_y2() = canvas_height;
}
update_fixed_rulers ();
if (is_visible() && first_time) {
if (is_visible() && initial_ruler_update_required) {
/*
this is really dumb, but signal_size_allocate() gets emitted intermittently
depending on whether the canvas contents are visible or not.
we only want to do this once
*/
update_fixed_rulers();
tempo_map_changed (Change (0));
first_time = false;
} else {
redisplay_tempo ();
}
initial_ruler_update_required = false;
}
Resized (); /* EMIT_SIGNAL */
}
@ -414,6 +417,8 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
const SelectionData& data,
guint info, guint time)
{
cerr << "dropping, target = " << data.get_target() << endl;
if (data.get_target() == "regions") {
drop_regions (context, x, y, data, info, time);
} else {
@ -528,7 +533,7 @@ Editor::maybe_autoscroll (GdkEvent* event)
}
if (autoscroll_direction != last_autoscroll_direction) {
if ((autoscroll_direction != last_autoscroll_direction) || (leftmost_frame < frame < rightmost_frame)) {
stop_canvas_autoscroll ();
}
@ -542,14 +547,13 @@ Editor::maybe_autoscroll (GdkEvent* event)
gint
Editor::_autoscroll_canvas (void *arg)
{
return ((Editor *) arg)->autoscroll_canvas ();
return ((Editor *) arg)->autoscroll_canvas ();
}
gint
bool
Editor::autoscroll_canvas ()
{
jack_nframes_t new_frame;
bool keep_calling = true;
jack_nframes_t limit = max_frames - current_page_frames();
GdkEventMotion ev;
jack_nframes_t target_frame;
@ -570,10 +574,6 @@ Editor::autoscroll_canvas ()
target_frame = drag_info.current_pointer_frame + autoscroll_distance;
}
if (new_frame != leftmost_frame) {
reposition_x_origin (new_frame);
}
/* now fake a motion event to get the object that is being dragged to move too */
ev.type = GDK_MOTION_NOTIFY;
@ -593,20 +593,26 @@ Editor::autoscroll_canvas ()
/* connect the timeout so that we get called repeatedly */
autoscroll_timeout_tag = g_timeout_add (20, _autoscroll_canvas, this);
keep_calling = false;
autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
return false;
} else if (autoscroll_cnt == 50) { /* 0.5 seconds */
}
if (new_frame != leftmost_frame) {
reposition_x_origin (new_frame);
}
if (autoscroll_cnt == 50) { /* 0.5 seconds */
/* after about a while, speed up a bit by changing the timeout interval */
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/50.0f);
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/30.0f);
} else if (autoscroll_cnt == 75) { /* 1.0 seconds */
} else if (autoscroll_cnt == 150) { /* 1.0 seconds */
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/20.0f);
} else if (autoscroll_cnt == 100) { /* 1.5 seconds */
} else if (autoscroll_cnt == 300) { /* 1.5 seconds */
/* after about another while, speed up by increasing the shift per callback */
@ -614,7 +620,7 @@ Editor::autoscroll_canvas ()
}
return keep_calling;
return true;
}
void
@ -631,7 +637,7 @@ Editor::start_canvas_autoscroll (int dir)
autoscroll_cnt = 0;
/* do it right now, which will start the repeated callbacks */
autoscroll_canvas ();
}

View File

@ -210,7 +210,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path, AudioFileSource::Flag (0)));
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
}
catch (failed_constructor& err) {
@ -343,7 +343,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
path = s;
try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path, AudioFileSource::Flag (0)));
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
}
catch (failed_constructor& err) {

View File

@ -1110,9 +1110,9 @@ Editor::temporal_zoom_step (bool coarser)
nfpu = frames_per_unit;
if (coarser) {
nfpu *= 2.0;
nfpu *= 1.61803399;
} else {
nfpu = max(1.0,(nfpu/2.0));
nfpu = max(1.0,(nfpu/1.61803399));
}
temporal_zoom (nfpu);
@ -1251,22 +1251,22 @@ Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
{
if (!session) return;
jack_nframes_t range_before = frame - leftmost_frame;
double range_before = frame - leftmost_frame;
double new_fpu;
new_fpu = frames_per_unit;
if (coarser) {
new_fpu *= 2.0;
range_before *= 2;
new_fpu *= 1.61803399;
range_before *= 1.61803399;
} else {
new_fpu = max(1.0,(new_fpu/2.0));
range_before /= 2;
new_fpu = max(1.0,(new_fpu/1.61803399));
range_before /= 1.61803399;
}
if (new_fpu == frames_per_unit) return;
jack_nframes_t new_leftmost = frame - range_before;
jack_nframes_t new_leftmost = frame - (jack_nframes_t)range_before;
if (new_leftmost > frame) new_leftmost = 0;

View File

@ -819,9 +819,9 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
lower = lower - spacer;
} else {
upper = upper + spacer - lower;
lower = 0;
}
upper = upper + spacer;
range = (jack_nframes_t) floor (upper - lower);
if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
@ -1035,114 +1035,87 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
return 0;
}
TempoMap::BBTPointList::iterator i;
TempoMap::BBTPointList *zoomed_bbt_points;
TempoMap::BBTPointList::iterator i;
uint32_t beats = 0;
uint32_t bars = 0;
uint32_t tick = 0;
uint32_t skip;
uint32_t t;
uint32_t zoomed_beats = 0;
uint32_t zoomed_bars = 0;
uint32_t desirable_marks;
uint32_t magic_accent_number = 1;
gint nmarks;
char buf[64];
gint n;
jack_nframes_t pos;
jack_nframes_t frame_one_beats_worth;
jack_nframes_t frame_skip;
double frame_skip_error;
double accumulated_error;
bool bar_helper_on = true;
bool bar_helper_on = true;
BBT_Time previous_beat;
BBT_Time next_beat;
jack_nframes_t next_beat_pos;
jack_nframes_t ilower = (jack_nframes_t) floor (lower);
jack_nframes_t iupper = (jack_nframes_t) floor (upper);
if ((desirable_marks = maxchars / 6) == 0) {
if ((desirable_marks = maxchars / 7) == 0) {
return 0;
}
/* align the tick marks to whatever we're snapping to... */
if (snap_type == SnapToAThirdBeat) {
switch (snap_type) {
case SnapToAThirdBeat:
bbt_beat_subdivision = 3;
} else if (snap_type == SnapToAQuarterBeat) {
break;
case SnapToAQuarterBeat:
bbt_beat_subdivision = 4;
} else if (snap_type == SnapToAEighthBeat) {
break;
case SnapToAEighthBeat:
bbt_beat_subdivision = 8;
magic_accent_number = 2;
} else if (snap_type == SnapToASixteenthBeat) {
break;
case SnapToASixteenthBeat:
bbt_beat_subdivision = 16;
magic_accent_number = 4;
} else if (snap_type == SnapToAThirtysecondBeat) {
break;
case SnapToAThirtysecondBeat:
bbt_beat_subdivision = 32;
magic_accent_number = 8;
} else {
break;
default:
bbt_beat_subdivision = 4;
break;
}
/* First find what a beat's distance is, so we can start plotting stuff before the beginning of the ruler */
session->bbt_time(ilower,previous_beat);
previous_beat.ticks = 0;
next_beat = previous_beat;
if (session->tempo_map().meter_at(ilower).beats_per_bar() < (next_beat.beats + 1)) {
next_beat.bars += 1;
next_beat.beats = 1;
} else {
next_beat.beats += 1;
}
frame_one_beats_worth = session->tempo_map().frame_time(next_beat) - session->tempo_map().frame_time(previous_beat);
zoomed_bbt_points = session->tempo_map().get_points((ilower >= frame_one_beats_worth) ? ilower - frame_one_beats_worth : 0, iupper);
if (current_bbt_points == 0 || zoomed_bbt_points == 0 || zoomed_bbt_points->empty()) {
if (current_bbt_points == 0 || current_bbt_points->empty()) {
return 0;
}
for (i = current_bbt_points->begin(); i != current_bbt_points->end(); i++) {
if ((*i).type == TempoMap::Beat) {
beats++;
} else if ((*i).type == TempoMap::Bar) {
bars++;
}
}
i = current_bbt_points->end();
i--;
bars = (*i).bar - (*current_bbt_points->begin()).bar;
beats = current_bbt_points->size() - bars;
/*Only show the bar helper if there aren't many bars on the screen */
if (bars > 1) {
if (bars > 2) {
bar_helper_on = false;
}
for (i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end(); i++) {
if ((*i).type == TempoMap::Beat) {
zoomed_beats++;
} else if ((*i).type == TempoMap::Bar) {
zoomed_bars++;
}
}
if (desirable_marks > (beats / 4)) {
/* we're in beat land...*/
uint32_t tick = 0;
uint32_t skip;
uint32_t t;
jack_nframes_t frame_skip;
double frame_skip_error;
double accumulated_error;
double position_of_helper;
bool i_am_accented = false;
bool we_need_ticks = false;
position_of_helper = ilower + (30 * Editor::get_current_zoom ());
if (desirable_marks >= (beats * 2)) {
nmarks = (zoomed_beats * bbt_beat_subdivision) + 1;
if (desirable_marks >= (beats)) {
nmarks = ((beats + 1) * bbt_beat_subdivision) + 1;
we_need_ticks = true;
} else {
nmarks = zoomed_beats + 1;
nmarks = beats + 1;
}
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
@ -1151,17 +1124,14 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
(*marks)[0].position = ilower;
(*marks)[0].style = GtkCustomRulerMarkMicro;
for (n = 1, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
if ((*i).frame <= ilower && (bar_helper_on)) {
for (n = 1, i = current_bbt_points->begin(); n < nmarks && i != current_bbt_points->end(); i++) {
if ((*i).frame < ilower && (bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
(*marks)[0].label = g_strdup (buf);
} else {
if ((*i).type == TempoMap::Bar) {
tick = 0;
(((*i).frame < position_of_helper) && bar_helper_on) ?
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
(*marks)[n].label = g_strdup (buf);
@ -1170,7 +1140,6 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
n++;
} else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
tick = 0;
((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ?
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
if (((*i).beat % 2 == 1) || we_need_ticks) {
@ -1184,33 +1153,36 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
/* Find the next beat */
session->bbt_time((*i).frame, next_beat);
if (session->tempo_map().meter_at((*i).frame).beats_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat_pos = session->tempo_map().frame_time(next_beat);
/* Add the tick marks */
if (we_need_ticks) {
if (we_need_ticks && (*i).type != TempoMap::Bar) {
frame_skip = (jack_nframes_t) floor ((session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
frame_skip_error = ((session->frame_rate() * 60.0f) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())) - frame_skip;
/* Find the next beat */
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat_pos = session->tempo_map().frame_time(next_beat);
frame_skip = (jack_nframes_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
frame_skip_error -= frame_skip;
skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
pos = (*i).frame + frame_skip;
accumulated_error = frame_skip_error;
tick += skip;
tick = skip;
for (t = 0; tick < Meter::ticks_per_beat && pos <= next_beat_pos ; pos += frame_skip, tick += skip, ++t) {
for (t = 0; (tick < Meter::ticks_per_beat) && (n < nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
if (t % magic_accent_number == (magic_accent_number - 1)) {
i_am_accented = true;
@ -1247,23 +1219,22 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
}
delete zoomed_bbt_points;
return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures
} else {
/* we're in bar land */
if (desirable_marks < (uint32_t) (zoomed_bars / 256)) {
if (desirable_marks < (uint32_t) (bars / 256)) {
nmarks = 1;
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", zoomed_bars );
snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", bars );
(*marks)[0].style = GtkCustomRulerMarkMajor;
(*marks)[0].label = g_strdup (buf);
(*marks)[0].position = ilower;
} else if (desirable_marks < (uint32_t) (nmarks = (gint) (zoomed_bars / 64))) {
} else if (desirable_marks < (uint32_t) (nmarks = (gint) (bars / 64))) {
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
if ((*i).type == TempoMap::Bar) {
if ((*i).bar % 64 == 1) {
if ((*i).bar % 256 == 1) {
@ -1283,9 +1254,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
}
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 16))) {
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(bars / 16))) {
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
if ((*i).type == TempoMap::Bar) {
if ((*i).bar % 16 == 1) {
if ((*i).bar % 64 == 1) {
@ -1305,9 +1276,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
}
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 4))){
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(bars / 4))){
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; ++i) {
if ((*i).type == TempoMap::Bar) {
if ((*i).bar % 4 == 1) {
if ((*i).bar % 16 == 1) {
@ -1328,9 +1299,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
} else {
nmarks = zoomed_bars;
nmarks = bars;
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
if ((*i).type == TempoMap::Bar) {
if ((*i).bar % 4 == 1) {
snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
@ -1349,7 +1320,6 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
}
}
}
delete zoomed_bbt_points;
return nmarks;
}
}
@ -1448,9 +1418,9 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
lower = lower - spacer;
} else {
upper = upper + spacer;
lower = 0;
}
upper = upper + spacer;
range = iupper - ilower;
if (range < (fr / 50)) {

View File

@ -96,14 +96,36 @@ void
Editor::tempo_map_changed (Change ignored)
{
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::tempo_map_changed), ignored));
BBT_Time previous_beat, next_beat; // the beats previous to the leftmost frame and after the rightmost frame
session->bbt_time(leftmost_frame, previous_beat);
session->bbt_time(leftmost_frame + current_page_frames(), next_beat);
if (previous_beat.beats > 1) {
previous_beat.beats -= 1;
} else if (previous_beat.bars > 1) {
previous_beat.bars--;
previous_beat.beats += 1;
}
previous_beat.ticks = 0;
if (session->tempo_map().meter_at(leftmost_frame + current_page_frames()).beats_per_bar () > next_beat.beats + 1) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat.ticks = 0;
if (current_bbt_points) {
delete current_bbt_points;
delete current_bbt_points;
current_bbt_points = 0;
}
if (session) {
current_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames());
current_bbt_points = session->tempo_map().get_points (session->tempo_map().frame_time (previous_beat), session->tempo_map().frame_time (next_beat));
update_tempo_based_rulers ();
} else {
current_bbt_points = 0;
}
@ -114,11 +136,11 @@ Editor::tempo_map_changed (Change ignored)
void
Editor::redisplay_tempo ()
{
hide_measures ();
if (session && current_bbt_points) {
draw_measures ();
update_tempo_based_rulers ();
Glib::signal_idle().connect (mem_fun (*this, &Editor::lazy_hide_and_draw_measures));
} else {
hide_measures ();
}
}
@ -126,7 +148,7 @@ void
Editor::hide_measures ()
{
for (TimeLineList::iterator i = used_measure_lines.begin(); i != used_measure_lines.end(); ++i) {
(*i)->hide();
(*i)->hide();
free_measure_lines.push_back (*i);
}
used_measure_lines.clear ();
@ -149,6 +171,14 @@ Editor::get_time_line ()
return line;
}
bool
Editor::lazy_hide_and_draw_measures ()
{
hide_measures ();
draw_measures ();
return false;
}
void
Editor::draw_measures ()
{
@ -156,86 +186,63 @@ Editor::draw_measures ()
return;
}
TempoMap::BBTPointList::iterator i = current_bbt_points->begin();
TempoMap::BBTPoint& p = (*i);
TempoMap::BBTPointList::iterator i;
ArdourCanvas::SimpleLine *line;
gdouble xpos, last_xpos;
uint32_t cnt;
gdouble xpos;
double x1, x2, y1, y2, beat_density;
uint32_t beats = 0;
uint32_t bars = 0;
uint32_t color;
if (current_bbt_points == 0 || current_bbt_points->empty()) {
return;
}
cnt = 0;
last_xpos = 0;
track_canvas.get_scroll_region (x1, y1, x2, y2);
/* get the first bar spacing */
gdouble last_beat = DBL_MAX;
gdouble beat_spacing = 0;
i = current_bbt_points->end();
i--;
bars = (*i).bar - (*current_bbt_points->begin()).bar;
beats = current_bbt_points->size() - bars;
for (i = current_bbt_points->begin(); i != current_bbt_points->end() && beat_spacing == 0; ++i) {
TempoMap::BBTPoint& p = (*i);
beat_density = (beats * 10.0f) / track_canvas.get_width ();
switch (p.type) {
case TempoMap::Bar:
break;
case TempoMap::Beat:
xpos = frame_to_unit (p.frame);
if (last_beat < xpos) {
beat_spacing = xpos - last_beat;
}
last_beat = xpos;
}
}
if (beat_spacing < 3.0) {
/* if the lines are too close together, they become useless */
if (beat_density > 2.0f) {
/* if the lines are too close together, they become useless */
return;
}
double x1, x2, y1, y2;
track_canvas.get_scroll_region (x1, y1, x2, y2);
y2 = 1000000000.0f;
for (i = current_bbt_points->begin(); i != current_bbt_points->end(); ++i) {
p = (*i);
switch (p.type) {
switch ((*i).type) {
case TempoMap::Bar:
break;
case TempoMap::Beat:
xpos = frame_to_unit (p.frame);
if (p.beat == 1) {
if ((*i).beat == 1) {
color = color_map[cMeasureLineBeat];
} else {
color = color_map[cMeasureLineBar];
/* only draw beat lines if the gaps between beats
are large.
*/
/* only draw beat lines if the gaps between beats are large. */
if (beat_spacing < 4.0) {
break;
if (beat_density > 0.25) {
break;
}
}
if (cnt == 0 || xpos - last_xpos > 4.0) {
line = get_time_line ();
line->property_x1() = xpos;
line->property_x2() = xpos;
line->property_y2() = y2;
line->property_color_rgba() = color;
line->raise_to_top();
line->show();
last_xpos = xpos;
++cnt;
}
xpos = frame_to_unit ((*i).frame);
line = get_time_line ();
line->property_x1() = xpos;
line->property_x2() = xpos;
line->property_y2() = y2;
line->property_color_rgba() = color;
//line->raise_to_top();
line->show();
break;
}
}
@ -244,6 +251,7 @@ Editor::draw_measures ()
cursor_group->raise_to_top();
time_line_group->lower_to_bottom();
return;
}
void

View File

@ -183,8 +183,8 @@ MidiStreamView::setup_rec_box ()
assert(region);
region->set_position (_trackview.session().transport_frame(), this);
rec_regions.push_back (region);
/* catch it if it goes away */
region->GoingAway.connect (bind (mem_fun (*this, &MidiStreamView::remove_rec_region), region));
// rec regions are destroyed in setup_rec_box
/* we add the region later */
}
@ -252,6 +252,15 @@ MidiStreamView::setup_rec_box ()
last_rec_data_frame = 0;
/* remove temp regions */
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) {
list<boost::shared_ptr<Region> >::iterator tmp;
tmp = iter;
++tmp;
(*iter)->drop_references ();
iter = tmp;
}
rec_regions.clear();
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";

View File

@ -657,8 +657,8 @@ NewSessionDialog::reset_template()
void
NewSessionDialog::reset_recent()
{
/* Shamelessly ripped from ardour_ui.cc */
std::vector<string *> *sessions;
/* Shamelessly ripped from ardour_ui.cc */
std::vector<string *> *sessions;
std::vector<string *>::iterator i;
RecentSessionsSorter cmp;
@ -677,7 +677,7 @@ NewSessionDialog::reset_recent()
for (i = sessions->begin(); i != sessions->end(); ++i) {
std::vector<std::string*>* states;
std::vector<std::string*>* states;
std::vector<const gchar*> item;
std::string fullpath = *(*i);
@ -699,7 +699,7 @@ NewSessionDialog::reset_recent()
row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
row[recent_columns.fullpath] = fullpath;
if (states->size() > 1) {
if (states->size()) {
/* add the children */

View File

@ -152,7 +152,6 @@ OptionEditor::set_session (Session *s)
click_emphasis_path_entry.set_sensitive (false);
session_raid_entry.set_sensitive (false);
smpte_fps_combo.set_sensitive (false);
short_xfade_slider.set_sensitive (false);
smpte_offset_negative_button.set_sensitive (false);
@ -165,28 +164,9 @@ OptionEditor::set_session (Session *s)
click_path_entry.set_sensitive (true);
click_emphasis_path_entry.set_sensitive (true);
session_raid_entry.set_sensitive (true);
smpte_fps_combo.set_sensitive (true);
short_xfade_slider.set_sensitive (true);
smpte_offset_negative_button.set_sensitive (true);
if (!s->smpte_drop_frames) {
// non-drop frames
if (s->smpte_frames_per_second == 24.0)
smpte_fps_combo.set_active_text (_("24 FPS"));
else if (s->smpte_frames_per_second == 25.0)
smpte_fps_combo.set_active_text (_("25 FPS"));
else if (s->smpte_frames_per_second == 30.0)
smpte_fps_combo.set_active_text (_("30 FPS"));
else
smpte_fps_combo.set_active_text (_("???"));
} else {
// drop frames
if (floor(s->smpte_frames_per_second) == 29.0)
smpte_fps_combo.set_active_text (_("30 FPS drop"));
else
smpte_fps_combo.set_active_text (_("???"));
}
smpte_offset_clock.set_session (s);
smpte_offset_clock.set (s->smpte_offset (), true);
@ -352,15 +332,6 @@ OptionEditor::setup_sync_options ()
HBox* hbox;
vector<string> dumb;
dumb.clear ();
dumb.push_back (X_("24 FPS"));
dumb.push_back (X_("25 FPS"));
dumb.push_back (X_("30 FPS drop"));
dumb.push_back (X_("30 FPS non-drop"));
set_popdown_strings (smpte_fps_combo, dumb);
smpte_fps_combo.signal_changed().connect (mem_fun(*this, &OptionEditor::smpte_fps_chosen));
smpte_offset_clock.set_mode (AudioClock::SMPTE);
smpte_offset_clock.ValueChanged.connect (mem_fun(*this, &OptionEditor::smpte_offset_chosen));
@ -368,19 +339,9 @@ OptionEditor::setup_sync_options ()
smpte_offset_negative_button.unset_flags (Gtk::CAN_FOCUS);
Label *smpte_fps_label = manage (new Label (_("SMPTE Frames/second")));
Label *smpte_offset_label = manage (new Label (_("SMPTE Offset")));
smpte_fps_label->set_name("OptionsLabel");
smpte_offset_label->set_name("OptionsLabel");
hbox = manage (new HBox);
hbox->set_border_width (5);
hbox->set_spacing (10);
hbox->pack_start (*smpte_fps_label, false, false);
hbox->pack_start (smpte_fps_combo, false, false);
sync_packer.pack_start (*hbox, false, false);
hbox = manage (new HBox);
hbox->set_border_width (5);
hbox->set_spacing (10);
@ -401,24 +362,6 @@ OptionEditor::smpte_offset_negative_clicked ()
}
}
void
OptionEditor::smpte_fps_chosen ()
{
if (session) {
string str = smpte_fps_combo.get_active_text();
if (str == X_("24 FPS")) {
session->set_smpte_type (24.0, false);
} else if (str == X_("25 FPS")) {
session->set_smpte_type (25.0, false);
} else if (str == X_("30 FPS drop")) {
session->set_smpte_type (29.97, true);
} else if (str == X_("30 FPS non-drop")) {
session->set_smpte_type (30.0, false);
}
}
}
void
OptionEditor::smpte_offset_chosen()
{

View File

@ -100,13 +100,11 @@ class OptionEditor : public Gtk::Dialog
Gtk::VBox sync_packer;
Gtk::ComboBoxText slave_type_combo;
Gtk::ComboBoxText smpte_fps_combo;
AudioClock smpte_offset_clock;
Gtk::CheckButton smpte_offset_negative_button;
void setup_sync_options ();
void smpte_fps_chosen ();
void smpte_offset_chosen ();
void smpte_offset_negative_clicked ();

View File

@ -26,16 +26,12 @@ class AudioRegionGainLine : public AutomationLine
void remove_point (ControlPoint&);
PBD::ID id() { return _id; }
private:
ARDOUR::Session& session;
AudioRegionView& rv;
UndoAction get_memento();
PBD::ID _id;
};

View File

@ -118,18 +118,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
hide_button.add (*(manage (new Image (get_xpm("small_x.xpm")))));
solo_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
mute_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
playlist_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
automation_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
size_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
visual_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
hide_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
edit_group_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::edit_click), false);
playlist_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::playlist_click));
automation_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::automation_click));
@ -137,10 +125,14 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click));
hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click));
solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
if (is_track()) {
rec_enable_button->set_active (false);
rec_enable_button->set_name ("TrackRecordEnableButton");
rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
@ -197,6 +189,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
_route->name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
if (is_track()) {
track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen));
@ -215,6 +208,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler));
}
RouteTimeAxisView::~RouteTimeAxisView ()
@ -605,19 +599,19 @@ RouteTimeAxisView::set_height (TrackHeight h)
show_name_entry ();
hide_name_label ();
mute_button->show_all();
solo_button->show_all();
mute_button->show();
solo_button->show();
if (rec_enable_button)
rec_enable_button->show_all();
rec_enable_button->show();
edit_group_button.show_all();
hide_button.show_all();
visual_button.show_all();
size_button.show_all();
automation_button.show_all();
edit_group_button.show();
hide_button.show();
visual_button.show();
size_button.show();
automation_button.show();
if (is_track() && track()->mode() == ARDOUR::Normal) {
playlist_button.show_all();
playlist_button.show();
}
break;
@ -625,10 +619,10 @@ RouteTimeAxisView::set_height (TrackHeight h)
show_name_entry ();
hide_name_label ();
mute_button->show_all();
solo_button->show_all();
mute_button->show();
solo_button->show();
if (rec_enable_button)
rec_enable_button->show_all();
rec_enable_button->show();
edit_group_button.hide ();
hide_button.hide ();
@ -1193,13 +1187,6 @@ RouteTimeAxisView::color_handler (ColorID id, uint32_t val)
}
}
bool
RouteTimeAxisView::select_me (GdkEventButton* ev)
{
editor.get_selection().add (this);
return false;
}
void
RouteTimeAxisView::show_all_automation ()
{

View File

@ -214,8 +214,7 @@ protected:
void map_frozen ();
void color_handler (ColorID, uint32_t);
bool select_me (GdkEventButton*);
void region_view_added (RegionView*);
void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);

View File

@ -86,10 +86,10 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
update_rec_display ();
}
mute_button->unset_flags (Gtk::CAN_FOCUS);
solo_button->unset_flags (Gtk::CAN_FOCUS);
/* map the current state */
map_frozen ();
@ -100,7 +100,7 @@ RouteUI::~RouteUI()
delete mute_menu;
}
gint
bool
RouteUI::mute_press(GdkEventButton* ev)
{
if (!ignore_toggle) {
@ -161,7 +161,7 @@ RouteUI::mute_press(GdkEventButton* ev)
return true;
}
gint
bool
RouteUI::mute_release(GdkEventButton* ev)
{
if (!ignore_toggle) {
@ -175,7 +175,7 @@ RouteUI::mute_release(GdkEventButton* ev)
return true;
}
gint
bool
RouteUI::solo_press(GdkEventButton* ev)
{
if (!ignore_toggle) {
@ -255,7 +255,7 @@ RouteUI::solo_press(GdkEventButton* ev)
return true;
}
gint
bool
RouteUI::solo_release(GdkEventButton* ev)
{
if (!ignore_toggle) {
@ -271,7 +271,7 @@ RouteUI::solo_release(GdkEventButton* ev)
return true;
}
gint
bool
RouteUI::rec_enable_press(GdkEventButton* ev)
{
if (!ignore_toggle && is_track() && rec_enable_button) {

View File

@ -90,11 +90,11 @@ class RouteUI : public virtual AxisView
XMLNode* get_child_xml_node (const string & childname);
gint mute_press(GdkEventButton*);
gint mute_release(GdkEventButton*);
gint solo_press(GdkEventButton*);
gint solo_release(GdkEventButton*);
gint rec_enable_press(GdkEventButton*);
bool mute_press(GdkEventButton*);
bool mute_release(GdkEventButton*);
bool solo_press(GdkEventButton*);
bool solo_release(GdkEventButton*);
bool rec_enable_press(GdkEventButton*);
void solo_changed(void*);
void mute_changed(void*);

View File

@ -36,6 +36,7 @@
#include <ardour/source_factory.h>
#include "ardour_ui.h"
#include "editing.h"
#include "gui_thread.h"
#include "prompter.h"
#include "sfdb_ui.h"
@ -197,7 +198,7 @@ SoundFileBox::play_btn_clicked ()
for (int n = 0; n < sf_info.channels; ++n) {
try {
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
srclist.push_back(afs);
} catch (failed_constructor& err) {
@ -305,6 +306,15 @@ SoundFileBox::field_selected ()
}
}
// this needs to be kept in sync with the ImportMode enum defined in editing.h and editing_syms.h.
static const char *import_mode_strings[] = {
X_("Add to Region list"),
X_("Add to selected Track(s)"),
X_("Add as new Track(s)"),
X_("Add as new Tape Track(s)"),
0
};
SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
: ArdourDialog (title, false),
chooser (Gtk::FILE_CHOOSER_ACTION_OPEN)
@ -339,13 +349,6 @@ SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
show_all ();
}
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, ARDOUR::Session* s)

View File

@ -178,6 +178,8 @@ StreamView::remove_region_view (boost::shared_ptr<Region> r)
}
}
#if 0
(unused)
void
StreamView::remove_rec_region (boost::shared_ptr<Region> r)
{
@ -195,6 +197,7 @@ StreamView::remove_rec_region (boost::shared_ptr<Region> r)
}
}
}
#endif
void
StreamView::undisplay_diskstream ()

View File

@ -109,7 +109,7 @@ protected:
virtual void add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves) = 0;
virtual void remove_region_view (boost::shared_ptr<ARDOUR::Region> );
void remove_rec_region (boost::shared_ptr<ARDOUR::Region>);
//void remove_rec_region (boost::shared_ptr<ARDOUR::Region>); (unused)
void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void undisplay_diskstream ();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,439 @@
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CAAudioFile.h
=============================================================================*/
#ifndef __CAAudioFile_h__
#define __CAAudioFile_h__
#include <AvailabilityMacros.h>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioToolbox/AudioToolbox.h>
#else
#include <AudioToolbox.h>
#endif
#include "CAStreamBasicDescription.h"
#include "CABufferList.h"
#include "CAAudioChannelLayout.h"
#include "CAXException.h"
#include "CAMath.h"
#ifndef CAAF_USE_EXTAUDIOFILE
// option: use AudioToolbox/ExtAudioFile.h? Only available on Tiger.
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
// we are building software that must be deployable on Panther or earlier
#define CAAF_USE_EXTAUDIOFILE 0
#else
// else we require Tiger and can use the API
#define CAAF_USE_EXTAUDIOFILE 1
#endif
#endif
#ifndef MAC_OS_X_VERSION_10_4
// we have pre-Tiger headers; add our own declarations
typedef UInt32 AudioFileTypeID;
enum {
kExtAudioFileError_InvalidProperty = -66561,
kExtAudioFileError_InvalidPropertySize = -66562,
kExtAudioFileError_NonPCMClientFormat = -66563,
kExtAudioFileError_InvalidChannelMap = -66564, // number of channels doesn't match format
kExtAudioFileError_InvalidOperationOrder = -66565,
kExtAudioFileError_InvalidDataFormat = -66566,
kExtAudioFileError_MaxPacketSizeUnknown = -66567,
kExtAudioFileError_InvalidSeek = -66568, // writing, or offset out of bounds
kExtAudioFileError_AsyncWriteTooLarge = -66569,
kExtAudioFileError_AsyncWriteBufferOverflow = -66570 // an async write could not be completed in time
};
#else
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioToolbox/ExtendedAudioFile.h>
#else
#include "ExtendedAudioFile.h"
#endif
#endif
// _______________________________________________________________________________________
// Wrapper class for an AudioFile, supporting encode/decode to/from a PCM client format
class CAAudioFile {
public:
// implementation-independent helpers
void Open(const char *filePath) {
FSRef fsref;
XThrowIfError(FSPathMakeRef((UInt8 *)filePath, &fsref, NULL), "locate audio file");
Open(fsref);
}
bool HasConverter() const { return GetConverter() != NULL; }
double GetDurationSeconds() {
double sr = GetFileDataFormat().mSampleRate;
return fnonzero(sr) ? GetNumberFrames() / sr : 0.;
}
// will be 0 if the file's frames/packet is 0 (variable)
// or the file's sample rate is 0 (unknown)
#if CAAF_USE_EXTAUDIOFILE
public:
CAAudioFile() : mExtAF(NULL) { }
virtual ~CAAudioFile() { if (mExtAF) Close(); }
void Open(const FSRef &fsref) {
// open an existing file
XThrowIfError(ExtAudioFileOpen(&fsref, &mExtAF), "ExtAudioFileOpen failed");
}
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL) {
XThrowIfError(ExtAudioFileCreateNew(&inParentDir, inFileName, inFileType, &inStreamDesc, inChannelLayout, &mExtAF), "ExtAudioFileCreateNew failed");
}
void Wrap(AudioFileID fileID, bool forWriting) {
// use this to wrap an AudioFileID opened externally
XThrowIfError(ExtAudioFileWrapAudioFileID(fileID, forWriting, &mExtAF), "ExtAudioFileWrapAudioFileID failed");
}
void Close() {
XThrowIfError(ExtAudioFileDispose(mExtAF), "ExtAudioFileClose failed");
mExtAF = NULL;
}
const CAStreamBasicDescription &GetFileDataFormat() {
UInt32 size = sizeof(mFileDataFormat);
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileDataFormat, &size, &mFileDataFormat), "Couldn't get file's data format");
return mFileDataFormat;
}
const CAAudioChannelLayout & GetFileChannelLayout() {
return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
}
void SetFileChannelLayout(const CAAudioChannelLayout &layout) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set file's channel layout");
mFileChannelLayout = layout;
}
const CAStreamBasicDescription &GetClientDataFormat() {
UInt32 size = sizeof(mClientDataFormat);
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, &size, &mClientDataFormat), "Couldn't get client data format");
return mClientDataFormat;
}
const CAAudioChannelLayout & GetClientChannelLayout() {
return FetchChannelLayout(mClientChannelLayout, kExtAudioFileProperty_ClientChannelLayout);
}
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat), "Couldn't set client format");
if (layout)
SetClientChannelLayout(*layout);
}
void SetClientChannelLayout(const CAAudioChannelLayout &layout) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set client channel layout");
}
AudioConverterRef GetConverter() const {
UInt32 size = sizeof(AudioConverterRef);
AudioConverterRef converter;
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_AudioConverter, &size, &converter), "Couldn't get file's AudioConverter");
return converter;
}
OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false)
{
OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData);
if (!inCanFail)
XThrowIfError(err, "Couldn't set audio converter property");
if (!err) {
// must tell the file that we have changed the converter; a NULL converter config is sufficient
CFPropertyListRef config = NULL;
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config), "couldn't signal the file that the converter has changed");
}
return err;
}
SInt64 GetNumberFrames() {
SInt64 length;
UInt32 size = sizeof(SInt64);
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, &size, &length), "Couldn't get file's length");
return length;
}
void SetNumberFrames(SInt64 length) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, sizeof(SInt64), &length), "Couldn't set file's length");
}
void Seek(SInt64 pos) {
XThrowIfError(ExtAudioFileSeek(mExtAF, pos), "Couldn't seek in audio file");
}
SInt64 Tell() {
SInt64 pos;
XThrowIfError(ExtAudioFileTell(mExtAF, &pos), "Couldn't get file's mark");
return pos;
}
void Read(UInt32 &ioFrames, AudioBufferList *ioData) {
XThrowIfError(ExtAudioFileRead(mExtAF, &ioFrames, ioData), "Couldn't read audio file");
}
void Write(UInt32 inFrames, const AudioBufferList *inData) {
XThrowIfError(ExtAudioFileWrite(mExtAF, inFrames, inData), "Couldn't write audio file");
}
void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_IOBufferSizeBytes, sizeof(UInt32), &bufferSizeBytes), "Couldn't set audio file's I/O buffer size");
}
private:
const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) {
UInt32 size;
XThrowIfError(ExtAudioFileGetPropertyInfo(mExtAF, propID, &size, NULL), "Couldn't get info about channel layout");
AudioChannelLayout *layout = (AudioChannelLayout *)malloc(size);
OSStatus err = ExtAudioFileGetProperty(mExtAF, propID, &size, layout);
if (err) {
free(layout);
XThrowIfError(err, "Couldn't get channel layout");
}
layoutObj = layout;
free(layout);
return layoutObj;
}
private:
ExtAudioFileRef mExtAF;
CAStreamBasicDescription mFileDataFormat;
CAAudioChannelLayout mFileChannelLayout;
CAStreamBasicDescription mClientDataFormat;
CAAudioChannelLayout mClientChannelLayout;
#endif
#if !CAAF_USE_EXTAUDIOFILE
CAAudioFile();
virtual ~CAAudioFile();
// --- second-stage initializers ---
// Use exactly one of the following:
// - Open
// - PrepareNew followed by Create
// - Wrap
void Open(const FSRef &fsref);
// open an existing file
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL);
void Wrap(AudioFileID fileID, bool forWriting);
// use this to wrap an AudioFileID opened externally
// ---
void Close();
// In case you want to close the file before the destructor executes
// --- Data formats ---
// Allow specifying the file's channel layout. Must be called before SetClientFormat.
// When writing, the specified channel layout is written to the file (if the file format supports
// the channel layout). When reading, the specified layout overrides the one read from the file,
// if any.
void SetFileChannelLayout(const CAAudioChannelLayout &layout);
// This specifies the data format which the client will use for reading/writing the file,
// which may be different from the file's format. An AudioConverter is created if necessary.
// The client format must be linear PCM.
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL);
void SetClientDataFormat(const CAStreamBasicDescription &dataFormat) { SetClientFormat(dataFormat, NULL); }
void SetClientChannelLayout(const CAAudioChannelLayout &layout) { SetClientFormat(mClientDataFormat, &layout); }
// Wrapping the underlying converter, if there is one
OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID,
UInt32 inPropertyDataSize,
const void * inPropertyData,
bool inCanFail = false);
void SetConverterConfig(CFArrayRef config) {
SetConverterProperty(kAudioConverterPropertySettings, sizeof(config), &config); }
CFArrayRef GetConverterConfig();
// --- I/O ---
// All I/O is sequential, but you can seek to an arbitrary position when reading.
// SeekToPacket and TellPacket's packet numbers are in the file's data format, not the client's.
// However, ReadPackets/WritePackets use packet counts in the client data format.
void Read(UInt32 &ioNumFrames, AudioBufferList *ioData);
void Write(UInt32 numFrames, const AudioBufferList *data);
// These can fail for files without a constant mFramesPerPacket
void Seek(SInt64 frameNumber);
SInt64 Tell() const; // frameNumber
// --- Accessors ---
// note: client parameters only valid if SetClientFormat has been called
AudioFileID GetAudioFileID() const { return mAudioFile; }
const CAStreamBasicDescription &GetFileDataFormat() const { return mFileDataFormat; }
const CAStreamBasicDescription &GetClientDataFormat() const { return mClientDataFormat; }
const CAAudioChannelLayout & GetFileChannelLayout() const { return mFileChannelLayout; }
const CAAudioChannelLayout & GetClientChannelLayout() const { return mClientChannelLayout; }
AudioConverterRef GetConverter() const { return mConverter; }
UInt32 GetFileMaxPacketSize() const { return mFileMaxPacketSize; }
UInt32 GetClientMaxPacketSize() const { return mClientMaxPacketSize; }
SInt64 GetNumberPackets() const {
SInt64 npackets;
UInt32 propertySize = sizeof(npackets);
XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &npackets), "get audio file's packet count");
return npackets;
}
SInt64 GetNumberFrames() const;
// will be 0 if the file's frames/packet is 0 (variable)
void SetNumberFrames(SInt64 length); // should only be set on a PCM file
// --- Tunable performance parameters ---
void SetUseCache(bool b) { mUseCache = b; }
void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { mIOBufferSizeBytes = bufferSizeBytes; }
UInt32 GetIOBufferSizeBytes() { return mIOBufferSizeBytes; }
void * GetIOBuffer() { return mIOBufferList.mBuffers[0].mData; }
void SetIOBuffer(void *buf);
// -- Profiling ---
#if CAAUDIOFILE_PROFILE
void EnableProfiling(bool b) { mProfiling = b; }
UInt64 TicksInConverter() const { return (mTicksInConverter > 0) ? (mTicksInConverter - mTicksInReadInConverter) : 0; }
UInt64 TicksInIO() const { return mTicksInIO; }
#endif
// _______________________________________________________________________________________
private:
SInt64 FileDataOffset();
void SeekToPacket(SInt64 packetNumber);
SInt64 TellPacket() const { return mPacketMark; } // will be imprecise if SeekToFrame was called
void SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout);
void WritePacketsFromCallback(
AudioConverterComplexInputDataProc inInputDataProc,
void * inInputDataProcUserData);
// will use I/O buffer size
void InitFileMaxPacketSize();
void FileFormatChanged(const FSRef *parentDir=0, CFStringRef filename=0, AudioFileTypeID filetype=0);
void GetExistingFileInfo();
void FlushEncoder();
void CloseConverter();
void UpdateClientMaxPacketSize();
void AllocateBuffers(bool okToFail=false);
SInt64 PacketToFrame(SInt64 packet) const;
SInt64 FrameToPacket(SInt64 inFrame) const;
static OSStatus ReadInputProc( AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
void* inUserData);
static OSStatus WriteInputProc( AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
void* inUserData);
// _______________________________________________________________________________________
private:
// the file
FSRef mFSRef;
AudioFileID mAudioFile;
bool mOwnOpenFile;
bool mUseCache;
bool mFinishingEncoding;
enum { kClosed, kReading, kPreparingToCreate, kPreparingToWrite, kWriting } mMode;
// SInt64 mNumberPackets; // in file's format
SInt64 mFileDataOffset;
SInt64 mPacketMark; // in file's format
SInt64 mFrameMark; // this may be offset from the start of the file
// by the codec's latency; i.e. our frame 0 could
// lie at frame 2112 of a decoded AAC file
SInt32 mFrame0Offset;
UInt32 mFramesToSkipFollowingSeek;
// buffers
UInt32 mIOBufferSizeBytes;
UInt32 mIOBufferSizePackets;
AudioBufferList mIOBufferList; // only one buffer -- USE ACCESSOR so it can be lazily initialized
bool mClientOwnsIOBuffer;
AudioStreamPacketDescription *mPacketDescs;
UInt32 mNumPacketDescs;
// formats/conversion
AudioConverterRef mConverter;
CAStreamBasicDescription mFileDataFormat;
CAStreamBasicDescription mClientDataFormat;
CAAudioChannelLayout mFileChannelLayout;
CAAudioChannelLayout mClientChannelLayout;
UInt32 mFileMaxPacketSize;
UInt32 mClientMaxPacketSize;
// cookie
Byte * mMagicCookie;
UInt32 mMagicCookieSize;
// for ReadPackets
UInt32 mMaxPacketsToRead;
// for WritePackets
UInt32 mWritePackets;
CABufferList * mWriteBufferList;
#if CAAUDIOFILE_PROFILE
// performance
bool mProfiling;
UInt64 mTicksInConverter;
UInt64 mTicksInReadInConverter;
UInt64 mTicksInIO;
bool mInConverter;
#endif
#endif // CAAF_USE_EXTAUDIOFILE
};
#endif // __CAAudioFile_h__

View File

@ -0,0 +1,179 @@
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CABufferList.cpp
=============================================================================*/
#include "CABufferList.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreServices/CoreServices.h>
#else
#include <Endian.h>
#endif
void CABufferList::AllocateBuffers(UInt32 nBytes)
{
if (nBytes <= GetNumBytes()) return;
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // get page faults now, not later
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
if (buf->mData != NULL && buf->mDataByteSize > 0)
// preserve existing buffer contents
memcpy(p, buf->mData, buf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
delete[] oldMemory;
}
void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
{
if (mNumberBuffers != inSrcList->mNumberBuffers) return;
if (mNumberBuffers != inSetPtrList->mNumberBuffers) return;
if (nBytes <= GetNumBytes()) {
CopyAllFrom(inSrcList, inSetPtrList);
return;
}
inSetPtrList->VerifyNotTrashingOwnedBuffer();
UInt32 fromByteSize = inSrcList->GetNumBytes();
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // make buffer "hot"
AudioBuffer *buf = mBuffers;
AudioBuffer *ptrBuf = inSetPtrList->mBuffers;
AudioBuffer *srcBuf = inSrcList->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
// preserve existing buffer contents
memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
ptrBuf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
if (inSrcList != inSetPtrList)
inSrcList->BytesConsumed(fromByteSize);
delete[] oldMemory;
}
void CABufferList::DeallocateBuffers()
{
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mData = NULL;
buf->mDataByteSize = 0;
}
if (mBufferMemory != NULL) {
delete[] mBufferMemory;
mBufferMemory = NULL;
}
}
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
{
printf("AudioBufferList @ %p:\n", abl);
const AudioBuffer *buf = abl->mBuffers;
for (UInt32 i = 0; i < abl->mNumberBuffers; ++i, ++buf) {
printf(" [%2ld]: %2ldch, %5ld bytes @ %8p",
i, buf->mNumberChannels, buf->mDataByteSize, buf->mData);
if (framesToPrint) {
printf(":");
Byte *p = (Byte *)buf->mData;
for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
switch (wordSize) {
case 0:
printf(" %6.3f", *(Float32 *)p);
p += sizeof(Float32);
break;
case 1:
case -1:
printf(" %02X", *p);
p += 1;
break;
case 2:
printf(" %04X", EndianU16_BtoN(*(UInt16 *)p));
p += 2;
break;
case 3:
printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
p += 3;
break;
case 4:
printf(" %08lX", EndianU32_BtoN(*(UInt32 *)p));
p += 4;
break;
case -2:
printf(" %04X", EndianU16_LtoN(*(UInt16 *)p));
p += 2;
break;
case -3:
printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
p += 3;
break;
case -4:
printf(" %08lX", EndianU32_LtoN(*(UInt32 *)p));
p += 4;
break;
}
}
printf("\n");
}
}

View File

@ -0,0 +1,300 @@
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CABufferList.h
=============================================================================*/
#ifndef __CABufferList_h__
#define __CABufferList_h__
#include <stddef.h>
#include "CAStreamBasicDescription.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreServices/CoreServices.h>
#else
#include <AssertMacros.h>
#endif
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
// wordSize: 0 = float32, else integer word size, negative if little-endian
/* ____________________________________________________________________________
// CABufferList - variable length buffer list
This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
is preferred.
CABufferList can be used in one of two ways:
- as mutable pointers into non-owned memory
- as an immutable array of buffers (owns its own memory).
All buffers are assumed to have the same format (number of channels, word size), so that
we can assume their mDataByteSizes are all the same.
____________________________________________________________________________ */
class CABufferList {
public:
void * operator new(size_t /*size*/, int nBuffers) {
return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
}
static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
{
UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
}
protected:
CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
mName(name),
mBufferMemory(NULL)
{
check(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
mNumberBuffers = numBuffers;
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mNumberChannels = channelsPerBuffer;
buf->mDataByteSize = 0;
buf->mData = NULL;
}
}
public:
~CABufferList()
{
if (mBufferMemory)
delete[] mBufferMemory;
}
const char * Name() { return mName; }
const AudioBufferList & GetBufferList() const { return *(AudioBufferList *)&mNumberBuffers; }
AudioBufferList & GetModifiableBufferList()
{
VerifyNotTrashingOwnedBuffer();
return _GetBufferList();
}
UInt32 GetNumBytes() const
{
return mBuffers[0].mDataByteSize;
}
void SetBytes(UInt32 nBytes, void *data)
{
VerifyNotTrashingOwnedBuffer();
check(mNumberBuffers == 1);
mBuffers[0].mDataByteSize = nBytes;
mBuffers[0].mData = data;
}
void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
// copies bytes from srcbl
// make ptrbl reflect the length copied
// note that srcbl may be same as ptrbl!
{
// Note that this buffer *can* own memory and its pointers/lengths are not
// altered; only its buffer contents, which are copied from srcbl.
// The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
// of the copied data, and srcbl's contents are consumed.
ptrbl->VerifyNotTrashingOwnedBuffer();
UInt32 nBytes = srcbl->GetNumBytes();
AudioBuffer *mybuf = mBuffers, *srcbuf = srcbl->mBuffers,
*ptrbuf = ptrbl->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
ptrbuf->mData = mybuf->mData;
ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
}
if (srcbl != ptrbl)
srcbl->BytesConsumed(nBytes);
}
void AppendFrom(CABufferList *blp, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *mybuf = mBuffers, *srcbuf = blp->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
check(nBytes <= srcbuf->mDataByteSize);
memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
mybuf->mDataByteSize += nBytes;
}
blp->BytesConsumed(nBytes);
}
void PadWithZeroes(UInt32 desiredBufferSize)
// for cases where an algorithm (e.g. SRC) requires some
// padding to create silence following end-of-file
{
VerifyNotTrashingOwnedBuffer();
if (GetNumBytes() > desiredBufferSize) return;
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
buf->mDataByteSize = desiredBufferSize;
}
}
void SetToZeroes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData, 0, nBytes);
buf->mDataByteSize = nBytes;
}
}
void Reset()
{
DeallocateBuffers();
}
Boolean SameDataAs(const CABufferList* anotherBufferList)
{
// check to see if two buffer lists point to the same memory.
if (mNumberBuffers != anotherBufferList->mNumberBuffers) return false;
for (UInt32 i = 0; i < mNumberBuffers; ++i) {
if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false;
}
return true;
}
void BytesConsumed(UInt32 nBytes)
// advance buffer pointers, decrease buffer sizes
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
check(nBytes <= buf->mDataByteSize);
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetFrom(const AudioBufferList *abl)
{
VerifyNotTrashingOwnedBuffer();
memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
}
void SetFrom(const CABufferList *blp)
{
SetFrom(&blp->GetBufferList());
}
void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *mybuf = mBuffers;
const AudioBuffer *srcbuf = abl->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
mybuf->mNumberChannels = srcbuf->mNumberChannels;
mybuf->mDataByteSize = nBytes;
mybuf->mData = srcbuf->mData;
}
}
void SetFrom(const CABufferList *blp, UInt32 nBytes)
{
SetFrom(&blp->GetBufferList(), nBytes);
}
AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
{
memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mNumberBuffers] - (char *)abl);
return abl;
}
void AllocateBuffers(UInt32 nBytes);
void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
void DeallocateBuffers();
void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
void AdvanceBufferPointers(UInt32 nBytes)
// this is for bufferlists that function simply as
// an array of pointers into another bufferlist, being advanced,
// as in RenderOutput implementations
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetNumBytes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf)
buf->mDataByteSize = nBytes;
}
void Print(const char *label=NULL, int nframes=0, int wordSize=0) const
{
if (label == NULL)
label = mName;
printf("%s - ", label);
CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
if (mBufferMemory)
printf(" owned memory @ 0x%p:\n", mBufferMemory);
}
protected:
AudioBufferList & _GetBufferList() { return *(AudioBufferList *)&mNumberBuffers; } // use with care
// if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
void VerifyNotTrashingOwnedBuffer()
{
// This needs to be called from places where we are modifying the buffer list.
// It's an error to modify the buffer pointers or lengths if we own the buffer memory.
check(mBufferMemory == NULL);
}
const char * mName; // for debugging
Byte * mBufferMemory;
// the rest must exactly mirror the structure of AudioBufferList
UInt32 mNumberBuffers;
AudioBuffer mBuffers[1];
};
#endif // __CABufferList_h__

View File

@ -0,0 +1,45 @@
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CAXException.cpp
=============================================================================*/
#include "CAXException.h"
CAXException::WarningHandler CAXException::sWarningHandler = NULL;

View File

@ -0,0 +1,158 @@
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CAXException.h
=============================================================================*/
#ifndef __CAXException_h__
#define __CAXException_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreServices/CoreServices.h>
#else
#include <ConditionalMacros.h>
#include <CoreServices.h>
#endif
#include "CADebugMacros.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
// An extended exception class that includes the name of the failed operation
class CAXException {
public:
CAXException(const char *operation, OSStatus err) :
mError(err)
{
if (operation == NULL)
mOperation[0] = '\0';
else if (strlen(operation) >= sizeof(mOperation)) {
memcpy(mOperation, operation, sizeof(mOperation) - 1);
mOperation[sizeof(mOperation) - 1] = '\0';
} else
strcpy(mOperation, operation);
}
char *FormatError(char *str) const
{
return FormatError(str, mError);
}
char mOperation[256];
const OSStatus mError;
// -------------------------------------------------
typedef void (*WarningHandler)(const char *msg, OSStatus err);
/*static void Throw(const char *operation, OSStatus err)
{
throw CAXException(operation, err);
}*/
static char *FormatError(char *str, OSStatus error)
{
// see if it appears to be a 4-char-code
*(UInt32 *)(str + 1) = EndianU32_NtoB(error);
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
str[0] = str[5] = '\'';
str[6] = '\0';
} else
// no, format it as an integer
sprintf(str, "%ld", error);
return str;
}
static void Warning(const char *s, OSStatus error)
{
if (sWarningHandler)
(*sWarningHandler)(s, error);
}
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
private:
static WarningHandler sWarningHandler;
};
#if DEBUG || CoreAudio_Debug
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
char __buf[12]; \
DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\
STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
char __buf[12]; \
DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\
STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#else
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
throw CAXException(operation, __err); \
} \
} while (0)
#endif
#define XThrow(error, operation) XThrowIf(true, error, operation)
#define XThrowIfErr(error) XThrowIfError(error, #error)
#endif // __CAXException_h__

View File

@ -171,9 +171,27 @@ def CheckJackRecomputeLatencies(context):
context.Result(result)
return result
jack_video_frame_offset_test = """
#include <jack/transport.h>
int main(int argc, char** argv)
{
jack_position_t pos;
pos.valid & JackVideoFrameOffset;
return 0;
}
"""
def CheckJackVideoFrameOffset(context):
context.Message('Checking for JackVideoFrameOffset in jack_position_bits_t enum...')
result = context.TryLink(jack_video_frame_offset_test, '.c')
context.Result(result)
return result
conf = Configure(ardour, custom_tests = {
'CheckJackClientOpen' : CheckJackClientOpen,
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset
})
if conf.CheckJackClientOpen():
@ -182,6 +200,14 @@ if conf.CheckJackClientOpen():
if conf.CheckJackRecomputeLatencies():
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES")
if conf.CheckJackVideoFrameOffset():
ardour.Append(CXXFLAGS="-DHAVE_JACK_VIDEO_SUPPORT")
if conf.CheckFunc('jack_port_ensure_monitor'):
env.Append(CCFLAGS='-DHAVE_JACK_PORT_ENSURE_MONITOR')
else:
print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
#
# Optional header files
#

View File

@ -61,8 +61,6 @@ class AudioDiskstream : public Diskstream
AudioDiskstream (Session &, const XMLNode&);
~AudioDiskstream();
const PBD::ID& id() const { return _id; }
float playback_buffer_load() const;
float capture_buffer_load() const;

View File

@ -75,7 +75,7 @@ class AudioFileSource : public AudioSource {
int move_to_trash (const string trash_dir_name);
static bool is_empty (string path);
static bool is_empty (Session&, string path);
void mark_streaming_write_completed ();
void mark_take (string);
@ -104,16 +104,16 @@ class AudioFileSource : public AudioSource {
/* constructor to be called for existing external-to-session files */
AudioFileSource (std::string path, Flag flags);
AudioFileSource (Session&, std::string path, Flag flags);
/* constructor to be called for new in-session files */
AudioFileSource (std::string path, Flag flags,
AudioFileSource (Session&, std::string path, Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format);
/* constructor to be called for existing in-session files */
AudioFileSource (const XMLNode&);
AudioFileSource (Session&, const XMLNode&);
int init (string idstr, bool must_exist);
@ -121,7 +121,6 @@ class AudioFileSource : public AudioSource {
string _path;
Flag _flags;
string _take_id;
bool allow_remove_if_empty;
uint64_t timeline_position;
static string peak_dir;

View File

@ -111,6 +111,8 @@ class AudioPlaylist : public ARDOUR::Playlist
bool region_changed (Change, boost::shared_ptr<Region>);
void crossfade_changed (Change);
void add_crossfade (Crossfade&);
void source_offset_changed (boost::shared_ptr<AudioRegion> region);
};
} /* namespace ARDOUR */

View File

@ -174,6 +174,7 @@ class AudioRegion : public Region
void recompute_at_end ();
void envelope_changed (Change);
void source_offset_changed ();
mutable Curve _fade_in;
FadeShape _fade_in_shape;

View File

@ -47,8 +47,8 @@ const jack_nframes_t frames_per_peak = 256;
class AudioSource : public Source
{
public:
AudioSource (string name);
AudioSource (const XMLNode&);
AudioSource (Session&, string name);
AudioSource (Session&, const XMLNode&);
virtual ~AudioSource ();
virtual jack_nframes_t available_peaks (double zoom) const;

View File

@ -159,8 +159,6 @@ struct ControlEvent {
XMLNode &get_state(void);
int set_state (const XMLNode &s);
PBD::ID id() { return _id; }
void set_max_xval (double);
double get_max_xval() const { return max_xval; }
@ -189,7 +187,7 @@ struct ControlEvent {
static sigc::signal<void, AutomationList*> AutomationListCreated;
protected:
PBD::ID _id;
struct State : public ARDOUR::StateManager::State {
AutomationEventList events;

View File

@ -20,15 +20,16 @@
#ifndef __coreaudio_source_h__
#define __coreaudio_source_h__
#include <appleutility/CAAudioFile.h>
#include <ardour/audiofilesource.h>
#include <AudioToolbox/ExtendedAudioFile.h>
namespace ARDOUR {
class CoreAudioSource : public AudioFileSource {
public:
CoreAudioSource (const XMLNode&);
CoreAudioSource (const string& path_plus_channel, Flag);
CoreAudioSource (ARDOUR::Session&, const XMLNode&);
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag);
~CoreAudioSource ();
float sample_rate() const;
@ -45,7 +46,7 @@ class CoreAudioSource : public AudioFileSource {
private:
ExtAudioFileRef af;
mutable CAAudioFile af;
uint16_t n_channels;
mutable float *tmpbuf;

View File

@ -31,12 +31,12 @@ namespace ARDOUR {
class DestructiveFileSource : public SndFileSource {
public:
DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
DestructiveFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
DestructiveFileSource (std::string path, Flag flags);
DestructiveFileSource (Session&, std::string path, Flag flags);
DestructiveFileSource (const XMLNode&);
DestructiveFileSource (Session&, const XMLNode&);
~DestructiveFileSource ();
jack_nframes_t last_capture_start_frame() const;

View File

@ -92,7 +92,6 @@ class IO;
bool destructive() const { return _flags & Destructive; }
virtual void set_destructive (bool yn);
const PBD::ID& id() const { return _id; }
bool hidden() const { return _flags & Hidden; }
bool recordable() const { return _flags & Recordable; }
bool reversed() const { return _actual_speed < 0.0f; }
@ -243,7 +242,6 @@ class IO;
ARDOUR::Session& _session;
ARDOUR::IO* _io;
ChanCount _n_channels;
PBD::ID _id;
Playlist* _playlist;
mutable gint _record_enabled;

View File

@ -263,8 +263,6 @@ public:
void start_pan_touch (uint32_t which);
void end_pan_touch (uint32_t which);
const PBD::ID& id() const { return _id; }
void defer_pan_reset ();
void allow_pan_reset ();
@ -292,7 +290,6 @@ public:
string _name;
Connection* _input_connection;
Connection* _output_connection;
PBD::ID _id;
bool no_panner_reset;
bool _phase_invert;
XMLNode* deferred_state;

View File

@ -121,10 +121,7 @@ class Location : public sigc::trackable, public PBD::StatefulDestructible
XMLNode& get_state (void);
int set_state (const XMLNode&);
PBD::ID id() { return _id; }
private:
PBD::ID _id;
string _name;
jack_nframes_t _start;
jack_nframes_t _end;
@ -150,7 +147,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
XMLNode& get_state (void);
int set_state (const XMLNode&);
PBD::ID id() { return _id; }
Location *get_location_by_id(PBD::ID);
Location* auto_loop_location () const;
@ -204,8 +200,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const;
PBD::ID _id;
};
} // namespace ARDOUR

View File

@ -43,8 +43,8 @@ class MidiRingBuffer;
class MidiSource : public Source
{
public:
MidiSource (string name);
MidiSource (const XMLNode&);
MidiSource (Session& session, string name);
MidiSource (Session& session, const XMLNode&);
virtual ~MidiSource ();
virtual jack_nframes_t read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const;

View File

@ -81,7 +81,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
EditMode get_edit_mode() const { return _edit_mode; }
void set_edit_mode (EditMode);
PBD::ID id() { return _id; }
/* Editing operations */
void add_region (boost::shared_ptr<Region>, jack_nframes_t position, float times = 1, bool with_save = true);
@ -279,8 +278,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
void unset_freeze_child (Playlist*);
void timestamp_layer_op (boost::shared_ptr<Region>);
PBD::ID _id;
};
} /* namespace ARDOUR */

View File

@ -103,7 +103,7 @@ class Port : public sigc::trackable {
void ensure_monitor_input (bool yn) {
#ifdef WITH_JACK_PORT_ENSURE_MONITOR
#ifdef HAVE_JACK_PORT_ENSURE_MONITOR
jack_port_ensure_monitor (_port, yn);
#else
jack_port_request_monitor(_port, yn);

View File

@ -37,7 +37,6 @@ class XMLNode;
namespace ARDOUR {
class Playlist;
class Source;
enum RegionEditState {
EditChangesNothing = 0,
@ -99,8 +98,6 @@ class Region : public PBD::StatefulDestructible, public StateManager, public boo
virtual ~Region();
const PBD::ID& id() const { return _id; }
/* Note: changing the name of a Region does not constitute an edit */
string name() const { return _name; }

View File

@ -267,8 +267,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
bool dirty() const { return _state_of_the_state & Dirty; }
sigc::signal<void> DirtyChanged;
std::string sound_dir () const;
std::string tape_dir () const;
std::string sound_dir (bool with_path = true) const;
std::string peak_dir () const;
std::string dead_sound_dir () const;
std::string automation_dir () const;
@ -281,7 +280,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string peak_path_from_audio_path (string);
string peak_path_from_audio_path (string) const;
string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
string midi_path_from_name (string);
@ -1713,9 +1713,10 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
uint32_t _total_free_4k_blocks;
Glib::Mutex space_lock;
static const char* old_sound_dir_name;
static const char* sound_dir_name;
static const char* tape_dir_name;
static const char* dead_sound_dir_name;
static const char* interchange_dir_name;
static const char* peak_dir_name;
string discover_best_sound_dir (bool destructive = false);

View File

@ -44,10 +44,10 @@ class SMFSource : public MidiSource {
};
/** Constructor for existing external-to-session files */
SMFSource (std::string path, Flag flags = Flag(0));
SMFSource (Session& session, std::string path, Flag flags = Flag(0));
/* Constructor for existing in-session files */
SMFSource (const XMLNode&);
SMFSource (Session& session, const XMLNode&);
virtual ~SMFSource ();

View File

@ -31,11 +31,11 @@ class SndFileSource : public AudioFileSource {
public:
/* constructor to be called for existing external-to-session files */
SndFileSource (std::string path, Flag flags);
SndFileSource (Session&, std::string path, Flag flags);
/* constructor to be called for new in-session files */
SndFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
SndFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::Removable|
AudioFileSource::RemovableIfEmpty|
@ -43,7 +43,7 @@ class SndFileSource : public AudioFileSource {
/* constructor to be called for existing in-session files */
SndFileSource (const XMLNode&);
SndFileSource (Session&, const XMLNode&);
~SndFileSource ();

View File

@ -32,11 +32,14 @@
namespace ARDOUR {
class Session;
class Source : public PBD::StatefulDestructible, public sigc::trackable
{
public:
Source (std::string name, DataType type);
Source (const XMLNode&);
Source (Session&, std::string name, DataType type);
Source (Session&, const XMLNode&);
virtual ~Source ();
std::string name() const { return _name; }
@ -44,8 +47,6 @@ class Source : public PBD::StatefulDestructible, public sigc::trackable
DataType type() { return _type; }
const PBD::ID& id() const { return _id; }
time_t timestamp() const { return _timestamp; }
void stamp (time_t when) { _timestamp = when; }
@ -65,13 +66,13 @@ class Source : public PBD::StatefulDestructible, public sigc::trackable
protected:
void update_length (jack_nframes_t pos, jack_nframes_t cnt);
Session& _session;
string _name;
DataType _type;
time_t _timestamp;
jack_nframes_t _length;
private:
PBD::ID _id;
};
}

View File

@ -13,14 +13,17 @@ class XMLNode;
namespace ARDOUR {
class Session;
class SourceFactory {
public:
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
static boost::shared_ptr<Source> create (const XMLNode& node);
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
static boost::shared_ptr<Source> createReadable (DataType type, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
static boost::shared_ptr<Source> createWritable (DataType type, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
// MIDI sources will have to be hacked in here somehow
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
};
}

View File

@ -242,7 +242,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
XMLNode& get_state (void);
int set_state (const XMLNode&);
PBD::ID id() { return _id; }
void dump (std::ostream&) const;
void clear ();
@ -320,8 +319,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
void save_state (std::string why);
PBD::ID _id;
};
}; /* namespace ARDOUR */

View File

@ -1590,7 +1590,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
string region_name;
_session.region_name (region_name, channels[0].write_source->name(), false);
cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
try {
boost::shared_ptr<Region> rx (RegionFactory::create (srcs, buffer_position, (*ci)->frames, region_name));
@ -1948,7 +1948,7 @@ AudioDiskstream::use_new_write_source (uint32_t n)
if (chan.write_source) {
if (AudioFileSource::is_empty (chan.write_source->path())) {
if (AudioFileSource::is_empty (_session, chan.write_source->path())) {
chan.write_source->mark_for_remove ();
chan.write_source.reset ();
} else {
@ -2185,7 +2185,8 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
}
try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, prop->value(), false, _session.frame_rate()));
fs = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, _session, prop->value(), false, _session.frame_rate()));
}
catch (failed_constructor& err) {

View File

@ -899,3 +899,4 @@ AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
}
}
}

View File

@ -167,6 +167,9 @@ AudioEngine::stop ()
bool
AudioEngine::get_sync_offset (jack_nframes_t& offset) const
{
#ifdef HAVE_JACK_VIDEO_SUPPORT
jack_position_t pos;
(void) jack_transport_query (_jack, &pos);
@ -176,6 +179,8 @@ AudioEngine::get_sync_offset (jack_nframes_t& offset) const
return true;
}
#endif
return false;
}

View File

@ -63,8 +63,8 @@ char AudioFileSource::bwf_country_code[3] = "US";
char AudioFileSource::bwf_organization_code[4] = "LAS";
char AudioFileSource::bwf_serial_number[13] = "000000000000";
AudioFileSource::AudioFileSource (string idstr, Flag flags)
: AudioSource (idstr), _flags (flags)
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
: AudioSource (s, idstr), _flags (flags)
{
/* constructor used for existing external to session files. file must exist already */
@ -74,8 +74,8 @@ AudioFileSource::AudioFileSource (string idstr, Flag flags)
}
AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
: AudioSource (path), _flags (flags)
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
: AudioSource (s, path), _flags (flags)
{
/* constructor used for new internal-to-session files. file cannot exist */
@ -84,8 +84,8 @@ AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat sam
}
}
AudioFileSource::AudioFileSource (const XMLNode& node)
: AudioSource (node), _flags (Flag (Writable|CanRename))
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
{
/* constructor used for existing internal-to-session files. file must exist */
@ -101,6 +101,7 @@ AudioFileSource::AudioFileSource (const XMLNode& node)
AudioFileSource::~AudioFileSource ()
{
if (removable()) {
cerr << "Removing file " << _path << " because its removable\n";
unlink (_path.c_str());
unlink (peakpath.c_str());
}
@ -109,7 +110,7 @@ AudioFileSource::~AudioFileSource ()
bool
AudioFileSource::removable () const
{
return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_path)));
return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
}
int
@ -135,7 +136,7 @@ AudioFileSource::init (string pathstr, bool must_exist)
string
AudioFileSource::peak_path (string audio_path)
{
return Session::peak_path_from_audio_path (audio_path);
return _session.peak_path_from_audio_path (audio_path);
}
string
@ -527,7 +528,7 @@ void
AudioFileSource::set_allow_remove_if_empty (bool yn)
{
if (writable()) {
allow_remove_if_empty = yn;
_flags = Flag (_flags | RemovableIfEmpty);
}
}
@ -561,11 +562,12 @@ AudioFileSource::set_name (string newname, bool destructive)
}
bool
AudioFileSource::is_empty (string path)
AudioFileSource::is_empty (Session& s, string path)
{
bool ret = false;
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createReadable (DataType::AUDIO, path, NoPeakFile, false));
SourceFactory::createReadable (DataType::AUDIO, s, path, NoPeakFile, false));
if (afs) {
ret = (afs->length() == 0);

View File

@ -51,7 +51,7 @@ AudioFilter::make_new_sources (boost::shared_ptr<AudioRegion> region, SourceList
try {
nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (
SourceFactory::createWritable (DataType::AUDIO, path, false, session.frame_rate())));
SourceFactory::createWritable (DataType::AUDIO, session, path, false, session.frame_rate())));
}
catch (failed_constructor& err) {

View File

@ -38,7 +38,7 @@
#include <ardour/dB.h>
#include <ardour/playlist.h>
#include <ardour/audiofilter.h>
#include <ardour/audiosource.h>
#include <ardour/audiofilesource.h>
#include "i18n.h"
#include <locale.h>
@ -71,6 +71,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
_fade_out (0.0, 2.0, 1.0, false),
_envelope (0.0, 2.0, 1.0, false)
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
}
_scale_amplitude = 1.0;
set_default_fades ();
@ -88,6 +93,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
, _fade_out (0.0, 2.0, 1.0, false)
, _envelope (0.0, 2.0, 1.0, false)
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
}
_scale_amplitude = 1.0;
set_default_fades ();
@ -180,6 +190,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
, _fade_out (0.0, 2.0, 1.0, false)
, _envelope (0.0, 2.0, 1.0, false)
{
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
}
set_default_fades ();
if (set_state (node)) {
@ -1165,6 +1180,12 @@ AudioRegion::speed_mismatch (float sr) const
return fsr != sr;
}
void
AudioRegion::source_offset_changed ()
{
set_position (source()->natural_position() + start(), this);
}
boost::shared_ptr<AudioSource>
AudioRegion::audio_source (uint32_t n) const
{

View File

@ -50,8 +50,8 @@ int AudioSource::peak_request_pipe[2];
bool AudioSource::_build_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false;
AudioSource::AudioSource (string name)
: Source (name, DataType::AUDIO)
AudioSource::AudioSource (Session& s, string name)
: Source (s, name, DataType::AUDIO)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
@ -63,8 +63,8 @@ AudioSource::AudioSource (string name)
_write_data_count = 0;
}
AudioSource::AudioSource (const XMLNode& node)
: Source (node)
AudioSource::AudioSource (Session& s, const XMLNode& node)
: Source (s, node)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;

View File

@ -20,6 +20,9 @@
#include <pbd/error.h>
#include <ardour/coreaudiosource.h>
#include <appleutility/CAAudioFile.h>
#include <appleutility/CAStreamBasicDescription.h>
#include "i18n.h"
#include <AudioToolbox/AudioFormat.h>
@ -27,14 +30,14 @@
using namespace ARDOUR;
using namespace PBD;
CoreAudioSource::CoreAudioSource (const XMLNode& node)
: AudioFileSource (node)
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
: AudioFileSource (s, node)
{
init (_name);
}
CoreAudioSource::CoreAudioSource (const string& idstr, Flag flags)
: AudioFileSource(idstr, flags)
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags)
: AudioFileSource(s, idstr, flags)
{
init (idstr);
}
@ -43,93 +46,48 @@ void
CoreAudioSource::init (const string& idstr)
{
string::size_type pos;
string file;
tmpbuf = 0;
tmpbufsize = 0;
af = 0;
OSStatus err = noErr;
_name = idstr;
if ((pos = idstr.find_last_of (':')) == string::npos) {
channel = 0;
file = idstr;
_path = idstr;
} else {
channel = atoi (idstr.substr (pos+1).c_str());
file = idstr.substr (0, pos);
_path = idstr.substr (0, pos);
}
/* note that we temporarily truncated _id at the colon */
FSRef fsr;
err = FSPathMakeRef ((UInt8*)file.c_str(), &fsr, 0);
if (err != noErr) {
error << string_compose (_("Could not make reference to file: %1"), name()) << endmsg;
throw failed_constructor();
}
err = ExtAudioFileOpen (&fsr, &af);
if (err != noErr) {
error << string_compose (_("Could not open file: %1"), name()) << endmsg;
ExtAudioFileDispose (af);
throw failed_constructor();
}
AudioStreamBasicDescription file_asbd;
memset(&file_asbd, 0, sizeof(AudioStreamBasicDescription));
size_t asbd_size = sizeof(AudioStreamBasicDescription);
err = ExtAudioFileGetProperty(af,
kExtAudioFileProperty_FileDataFormat, &asbd_size, &file_asbd);
if (err != noErr) {
error << string_compose (_("Could not get file data format for file: %1"), name()) << endmsg;
ExtAudioFileDispose (af);
throw failed_constructor();
}
n_channels = file_asbd.mChannelsPerFrame;
cerr << "number of channels: " << n_channels << endl;
cerr << "CoreAudioSource::init() " << name() << endl;
if (channel >= n_channels) {
error << string_compose(_("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number"), n_channels, channel) << endmsg;
ExtAudioFileDispose (af);
throw failed_constructor();
}
/* note that we temporarily truncated _id at the colon */
try {
af.Open(_path.c_str());
int64_t ca_frames;
size_t prop_size = sizeof(int64_t);
CAStreamBasicDescription file_asbd (af.GetFileDataFormat());
n_channels = file_asbd.NumberChannels();
cerr << "number of channels: " << n_channels << endl;
if (channel >= n_channels) {
error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, channel, name()) << endmsg;
throw failed_constructor();
}
err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &prop_size, &ca_frames);
if (err != noErr) {
error << string_compose (_("Could not get file length for file: %1"), name()) << endmsg;
ExtAudioFileDispose (af);
throw failed_constructor();
}
_length = af.GetNumberFrames();
_length = ca_frames;
_path = file;
AudioStreamBasicDescription client_asbd;
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
client_asbd.mSampleRate = file_asbd.mSampleRate;
client_asbd.mFormatID = kAudioFormatLinearPCM;
client_asbd.mFormatFlags = kLinearPCMFormatFlagIsFloat;
client_asbd.mBytesPerPacket = file_asbd.mChannelsPerFrame * 4;
client_asbd.mFramesPerPacket = 1;
client_asbd.mBytesPerFrame = client_asbd.mBytesPerPacket;
client_asbd.mChannelsPerFrame = file_asbd.mChannelsPerFrame;
client_asbd.mBitsPerChannel = 32;
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
if (err != noErr) {
error << string_compose (_("Could not set client data format for file: %1"), name()) << endmsg;
ExtAudioFileDispose (af);
CAStreamBasicDescription client_asbd(file_asbd);
client_asbd.SetCanonical(client_asbd.NumberChannels(), false);
af.SetClientFormat (client_asbd);
} catch (CAXException& cax) {
error << string_compose ("CoreAudioSource: %1 (%2)", cax.mOperation, name()) << endmsg;
throw failed_constructor ();
}
if (_build_peakfiles) {
if (initialize_peakfile (false, file)) {
error << string_compose(_("initialize peakfile failed for file %1"), name()) << endmsg;
ExtAudioFileDispose (af);
if (initialize_peakfile (false, _path)) {
error << string_compose("CoreAudioSource: initialize peakfile failed (%1)", name()) << endmsg;
throw failed_constructor ();
}
}
@ -137,41 +95,44 @@ CoreAudioSource::init (const string& idstr)
CoreAudioSource::~CoreAudioSource ()
{
cerr << "CoreAudioSource::~CoreAudioSource() " << name() << endl;
GoingAway (); /* EMIT SIGNAL */
if (af) {
ExtAudioFileDispose (af);
}
if (tmpbuf) {
delete [] tmpbuf;
}
cerr << "deletion done" << endl;
}
jack_nframes_t
CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
{
OSStatus err = noErr;
err = ExtAudioFileSeek(af, start);
if (err != noErr) {
error << string_compose(_("CoreAudioSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), err) << endmsg;
try {
af.Seek (start);
} catch (CAXException& cax) {
error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start, _name.substr (1)) << endmsg;
return 0;
}
AudioBufferList abl;
abl.mNumberBuffers = 1;
abl.mBuffers[0].mNumberChannels = n_channels;
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
abl.mBuffers[0].mData = dst;
UInt32 new_cnt = cnt;
if (n_channels == 1) {
err = ExtAudioFileRead(af, (UInt32*) &cnt, &abl);
_read_data_count = cnt * sizeof(float);
return cnt;
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
abl.mBuffers[0].mData = dst;
try {
af.Read (new_cnt, &abl);
} catch (CAXException& cax) {
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
}
_read_data_count = new_cnt * sizeof(float);
return new_cnt;
}
uint32_t real_cnt = cnt * n_channels;
UInt32 real_cnt = cnt * n_channels;
{
Glib::Mutex::Lock lm (_tmpbuf_lock);
@ -185,10 +146,16 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
tmpbuf = new float[tmpbufsize];
}
abl.mBuffers[0].mDataByteSize = real_cnt * sizeof(Sample);
abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample);
abl.mBuffers[0].mData = tmpbuf;
cerr << "channel: " << channel << endl;
err = ExtAudioFileRead(af, (UInt32*) &real_cnt, &abl);
try {
af.Read (real_cnt, &abl);
} catch (CAXException& cax) {
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
}
float *ptr = tmpbuf + channel;
real_cnt /= n_channels;
@ -208,15 +175,12 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
float
CoreAudioSource::sample_rate() const
{
AudioStreamBasicDescription client_asbd;
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
CAStreamBasicDescription client_asbd;
OSStatus err = noErr;
size_t asbd_size = sizeof(AudioStreamBasicDescription);
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
if (err != noErr) {
error << string_compose(_("Could not detect samplerate for: %1"), name()) << endmsg;
try {
client_asbd = af.GetClientDataFormat ();
} catch (CAXException& cax) {
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
return 0.0;
}
@ -228,4 +192,3 @@ CoreAudioSource::update_header (jack_nframes_t when, struct tm&, time_t)
{
return 0;
}

View File

@ -68,21 +68,21 @@ gain_t* DestructiveFileSource::out_coefficient = 0;
gain_t* DestructiveFileSource::in_coefficient = 0;
jack_nframes_t DestructiveFileSource::xfade_frames = 64;
DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
: SndFileSource (path, samp_format, hdr_format, rate, flags)
DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
: SndFileSource (s, path, samp_format, hdr_format, rate, flags)
{
init ();
}
DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
: SndFileSource (path, flags)
DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags)
: SndFileSource (s, path, flags)
{
init ();
}
DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
: SndFileSource (node)
DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node)
: SndFileSource (s, node)
{
init ();
}

View File

@ -375,7 +375,9 @@ ARDOUR::get_user_ardour_path ()
/* create it if necessary */
mkdir (path.c_str (), 0755);
if (g_mkdir_with_parents (path.c_str (), 0755)) {
throw exception ();
}
return path;
}

View File

@ -140,7 +140,7 @@ Session::import_audiofile (import_status& status)
try {
newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, buf, false, frame_rate()));
SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
}
catch (failed_constructor& err) {

View File

@ -20,6 +20,7 @@
#include <algorithm>
#include <unistd.h>
#include <locale.h>
#include <errno.h>
#include <sigc++/bind.h>
@ -2143,8 +2144,8 @@ IO::load_automation (const string& path)
fullpath += path;
in.open (fullpath.c_str());
if (!in) {
error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
return -1;
error << string_compose(_("%1: cannot open automation event file \"%2\" (%2)"), _name, fullpath, strerror (errno)) << endmsg;
return -1;
}
}

View File

@ -81,13 +81,18 @@ Location::set_start (jack_nframes_t s)
{
if (is_mark()) {
if (_start != s) {
_start = s;
_end = s;
start_changed(this); /* EMIT SIGNAL */
if ( is_start() ) {
Session::StartTimeChanged (); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset ( s );
}
if ( is_end() ) {
Session::EndTimeChanged (); /* EMIT SIGNAL */
}

View File

@ -42,15 +42,15 @@ using namespace PBD;
sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated;
MidiSource::MidiSource (string name)
: Source (name, DataType::MIDI)
MidiSource::MidiSource (Session& s, string name)
: Source (s, name, DataType::MIDI)
{
_read_data_count = 0;
_write_data_count = 0;
}
MidiSource::MidiSource (const XMLNode& node)
: Source (node)
MidiSource::MidiSource (Session& s, const XMLNode& node)
: Source (s, node)
{
_read_data_count = 0;
_write_data_count = 0;

View File

@ -1090,7 +1090,7 @@ Panner::save () const
ofstream out (automation_path.c_str());
if (!out) {
error << string_compose (_("cannot open pan automation file \"%1\" for saving (%s)"), automation_path, strerror (errno))
error << string_compose (_("cannot open pan automation file \"%1\" for saving (%2)"), automation_path, strerror (errno))
<< endmsg;
return -1;
}

View File

@ -224,13 +224,13 @@ Plugin::save_preset (string name, string domain)
free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
string path = string_compose("%1/.%2", envvar, domain);
if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
if (g_mkdir_with_parents (path.c_str(), 0775)) {
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false;
}
path += "/rdf";
if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
if (g_mkdir_with_parents (path.c_str(), 0775)) {
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false;
}

View File

@ -277,17 +277,17 @@ Route::process_output_buffers (BufferSet& bufs,
-------------------------------------------------------------------------------------------------- */
if (declick > 0) {
Amp::run (bufs, nframes, 0.0, 1.0, _phase_invert);
Amp::run (bufs, nframes, 0.0, 1.0, false);
_pending_declick = 0;
} else if (declick < 0) {
Amp::run (bufs, nframes, 1.0, 0.0, _phase_invert);
Amp::run (bufs, nframes, 1.0, 0.0, false);
_pending_declick = 0;
} else {
/* no global declick */
if (solo_gain != dsg) {
Amp::run (bufs, nframes, solo_gain, dsg, _phase_invert);
Amp::run (bufs, nframes, solo_gain, dsg, false);
solo_gain = dsg;
}
}
@ -302,7 +302,7 @@ Route::process_output_buffers (BufferSet& bufs,
}
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
Amp::run (bufs, nframes, mute_gain, dmg, false);
mute_gain = dmg;
mute_declick_applied = true;
}
@ -379,7 +379,7 @@ Route::process_output_buffers (BufferSet& bufs,
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
Amp::run (bufs, nframes, mute_gain, dmg, false);
mute_gain = dmg;
mute_declick_applied = true;
}
@ -543,7 +543,7 @@ Route::process_output_buffers (BufferSet& bufs,
}
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
Amp::run (bufs, nframes, mute_gain, dmg, false);
mute_gain = dmg;
mute_declick_applied = true;
}
@ -588,7 +588,7 @@ Route::process_output_buffers (BufferSet& bufs,
----------------------------------------------------------------------*/
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
Amp::run (bufs, nframes, mute_gain, dmg, false);
mute_gain = dmg;
mute_declick_applied = true;
}

View File

@ -87,10 +87,11 @@ using boost::shared_ptr;
const char* Session::_template_suffix = X_(".template");
const char* Session::_statefile_suffix = X_(".ardour");
const char* Session::_pending_suffix = X_(".pending");
const char* Session::sound_dir_name = X_("sounds");
const char* Session::tape_dir_name = X_("tapes");
const char* Session::old_sound_dir_name = X_("sounds");
const char* Session::sound_dir_name = X_("audiofiles");
const char* Session::peak_dir_name = X_("peaks");
const char* Session::dead_sound_dir_name = X_("dead_sounds");
const char* Session::interchange_dir_name = X_("interchange");
Session::compute_peak_t Session::compute_peak = 0;
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
@ -2836,17 +2837,11 @@ Session::source_by_id (const PBD::ID& id)
}
string
Session::peak_path_from_audio_path (string audio_path)
Session::peak_path_from_audio_path (string audio_path) const
{
/* XXX hardly bombproof! fix me */
string res;
res = Glib::path_get_dirname (audio_path);
res = Glib::path_get_dirname (res);
res += '/';
res += peak_dir_name;
res += '/';
res = peak_dir ();
res += PBD::basename_nosuffix (audio_path);
res += ".peak";
@ -2992,11 +2987,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
spath = (*i).path;
if (destructive) {
spath += tape_dir_name;
} else {
spath += sound_dir_name;
}
spath += sound_dir (false);
if (destructive) {
if (nchan < 2) {
@ -3032,9 +3023,10 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
}
}
if (access (buf, F_OK) == 0) {
if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
existing++;
}
}
}
if (existing == 0) {
@ -3053,11 +3045,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
string foo = buf;
if (destructive) {
spath = tape_dir ();
} else {
spath = discover_best_sound_dir ();
}
spath = discover_best_sound_dir ();
string::size_type pos = foo.find_last_of ('/');
@ -3074,7 +3062,8 @@ boost::shared_ptr<AudioFileSource>
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
{
string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive);
return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, spath, destructive, frame_rate()));
return boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
}
// FIXME: _terrible_ code duplication
@ -3260,7 +3249,7 @@ Session::create_midi_source_for_session (MidiDiskstream& ds)
{
string spath = midi_path_from_name (ds.name());
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, spath, false, frame_rate()));
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, spath, false, frame_rate()));
}
@ -3420,17 +3409,35 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
void
Session::remove_empty_sounds ()
{
PathScanner scanner;
string dir;
dir = sound_dir ();
vector<string *>* possible_audiofiles = scanner (dir, "\\.wav$", false, true);
vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64)$", false, true);
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
Glib::Mutex::Lock lm (source_lock);
regex_t compiled_tape_track_pattern;
int err;
if (AudioFileSource::is_empty (*(*i))) {
if ((err = regcomp (&compiled_tape_track_pattern, "/T[0-9][0-9][0-9][0-9]-", REG_EXTENDED|REG_NOSUB))) {
char msg[256];
regerror (err, &compiled_tape_track_pattern, msg, sizeof (msg));
error << string_compose (_("Cannot compile tape track regexp for use (%1)"), msg) << endmsg;
return;
}
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
/* never remove files that appear to be a tape track */
if (regexec (&compiled_tape_track_pattern, (*i)->c_str(), 0, 0, 0) == 0) {
delete *i;
continue;
}
if (AudioFileSource::is_empty (*this, *(*i))) {
unlink ((*i)->c_str());
@ -3610,7 +3617,7 @@ jack_nframes_t
Session::available_capture_duration ()
{
const double scale = 4096.0 / sizeof (Sample);
if (_total_free_4k_blocks * scale > (double) max_frames) {
return max_frames;
}
@ -3914,7 +3921,8 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
}
try {
fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, buf, false, frame_rate()));
fsource = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
}
catch (failed_constructor& err) {
@ -3931,7 +3939,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
to_do = len;
/* create a set of reasonably-sized buffers */
buffers.ensure_buffers(nchans, chunk_size);
buffers.ensure_buffers(nchans, chunk_size);
buffers.set_count(nchans);
while (to_do && !itt.cancel) {

View File

@ -309,7 +309,6 @@ Session::second_stage_init (bool new_session)
if (!new_session) {
if (load_state (_current_snapshot_name)) {
cerr << "load state failed\n";
return -1;
}
remove_empty_sounds ();
@ -371,7 +370,6 @@ Session::second_stage_init (bool new_session)
_end_location_is_free = false;
}
restore_history(_current_snapshot_name);
return 0;
}
@ -436,16 +434,7 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += sound_dir_name;
fspath += ':';
/* tape dir */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
fspath += sound_dir (false);
AudioFileSource::set_search_path (fspath);
SMFSource::set_search_path (fspath); // FIXME: should be different
@ -467,16 +456,7 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += sound_dir_name;
fspath += ':';
/* add tape dir to file search path */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
fspath += sound_dir (false);
fspath += ':';
remaining = remaining.substr (colon+1);
@ -492,15 +472,9 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += sound_dir_name;
fspath += sound_dir (false);
fspath += ':';
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
session_dirs.push_back (sp);
}
@ -518,61 +492,40 @@ int
Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
{
string dir;
new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
if (mkdir (_path.c_str(), 0755) < 0) {
if (errno == EEXIST) {
new_session = false;
} else {
error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
return -1;
}
} else {
new_session = true;
if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
return -1;
}
dir = peak_dir ();
if (mkdir (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = sound_dir ();
if (mkdir (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
}
dir = tape_dir ();
if (mkdir (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = dead_sound_dir ();
if (mkdir (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = automation_dir ();
if (mkdir (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
@ -725,6 +678,8 @@ Session::save_state (string snapshot_name, bool pending)
}
cerr << "actually writing state\n";
if (!tree.write (xml_path)) {
error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
@ -2031,13 +1986,12 @@ Session::load_sources (const XMLNode& node)
boost::shared_ptr<Source>
Session::XMLSourceFactory (const XMLNode& node)
{
if (node.name() != "Source") {
return boost::shared_ptr<Source>();
}
try {
return SourceFactory::create (node);
return SourceFactory::create (*this, node);
}
catch (failed_constructor& err) {
@ -2062,7 +2016,7 @@ Session::save_template (string template_name)
if ((dp = opendir (dir.c_str()))) {
closedir (dp);
} else {
if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
@ -2142,11 +2096,9 @@ Session::ensure_sound_dir (string path, string& result)
/* Ensure that the parent directory exists */
if (mkdir (path.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
return -1;
}
if (g_mkdir_with_parents (path.c_str(), 0775)) {
error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
return -1;
}
/* Ensure that the sounds directory exists */
@ -2155,33 +2107,27 @@ Session::ensure_sound_dir (string path, string& result)
result += '/';
result += sound_dir_name;
if (mkdir (result.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
return -1;
}
if (g_mkdir_with_parents (result.c_str(), 0775)) {
error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
return -1;
}
dead = path;
dead += '/';
dead += dead_sound_dir_name;
if (mkdir (dead.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
return -1;
}
if (g_mkdir_with_parents (dead.c_str(), 0775)) {
error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
return -1;
}
peak = path;
peak += '/';
peak += peak_dir_name;
if (mkdir (peak.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
return -1;
}
if (g_mkdir_with_parents (peak.c_str(), 0775)) {
error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
return -1;
}
/* callers expect this to be terminated ... */
@ -2196,12 +2142,6 @@ Session::discover_best_sound_dir (bool destructive)
vector<space_and_path>::iterator i;
string result;
/* destructive files all go into the same place */
if (destructive) {
return tape_dir();
}
/* handle common case without system calls */
if (session_dirs.size() == 1) {
@ -2418,20 +2358,37 @@ Session::dead_sound_dir () const
}
string
Session::sound_dir () const
Session::sound_dir (bool with_path) const
{
string res = _path;
/* support old session structure */
struct stat statbuf;
string old;
if (with_path) {
old = _path;
}
old += sound_dir_name;
old += '/';
if (stat (old.c_str(), &statbuf) == 0) {
return old;
}
string res;
if (with_path) {
res = _path;
}
res += interchange_dir_name;
res += '/';
res += legalize_for_path (_name);
res += '/';
res += sound_dir_name;
res += '/';
return res;
}
string
Session::tape_dir () const
{
string res = _path;
res += tape_dir_name;
res += '/';
return res;
}
@ -3427,8 +3384,7 @@ Session::save_history (string snapshot_name)
XMLTree tree;
string xml_path;
string bak_path;
tree.set_root (&history.get_state());
if (snapshot_name.empty()) {
@ -3436,7 +3392,6 @@ Session::save_history (string snapshot_name)
}
xml_path = _path + snapshot_name + ".history";
cerr << "Saving history to " << xml_path << endmsg;
bak_path = xml_path + ".bak";
@ -3447,6 +3402,8 @@ Session::save_history (string snapshot_name)
return -1;
}
cerr << "actually writing history\n";
if (!tree.write (xml_path))
{
error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;

View File

@ -51,7 +51,7 @@ Session::bbt_time (jack_nframes_t when, BBT_Time& bbt)
void
Session::sync_time_vars ()
{
_current_frame_rate = _base_frame_rate * (1.0 + (video_pullup/100.0) );
_current_frame_rate = (jack_nframes_t) round (_base_frame_rate * (1.0 + (video_pullup/100.0)));
_frames_per_hour = _current_frame_rate * 3600;
_frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
_smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
@ -432,9 +432,11 @@ Session::jack_timebase_callback (jack_transport_state_t state,
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
}
#ifdef HAVE_JACK_VIDEO_SUPPORT
//poke audio video ratio so Ardour can track Video Sync
pos->audio_frames_per_video_frame = frame_rate() / smpte_frames_per_second;
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
#endif
#if 0
/* SMPTE info */

View File

@ -82,8 +82,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
}
try {
sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, path, false, frame_rate())));
sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *this, path, false, frame_rate())));
} catch (failed_constructor& err) {
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;

View File

@ -48,8 +48,8 @@ bool SMFSource::header_position_negative;
uint64_t SMFSource::header_position_offset;
*/
SMFSource::SMFSource (std::string path, Flag flags)
: MidiSource (region_name_from_path(path))
SMFSource::SMFSource (Session& s, std::string path, Flag flags)
: MidiSource (s, region_name_from_path(path))
, _channel(0)
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
, _allow_remove_if_empty(true)
@ -72,8 +72,8 @@ SMFSource::SMFSource (std::string path, Flag flags)
assert(_name.find("/") == string::npos);
}
SMFSource::SMFSource (const XMLNode& node)
: MidiSource (node)
SMFSource::SMFSource (Session& s, const XMLNode& node)
: MidiSource (s, node)
, _channel(0)
, _flags (Flag (Writable|CanRename))
, _allow_remove_if_empty(true)

View File

@ -34,8 +34,8 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
SndFileSource::SndFileSource (const XMLNode& node)
: AudioFileSource (node)
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
: AudioFileSource (s, node)
{
init (_name);
@ -52,9 +52,9 @@ SndFileSource::SndFileSource (const XMLNode& node)
}
}
SndFileSource::SndFileSource (string idstr, Flag flags)
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
/* files created this way are never writable or removable */
: AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
init (idstr);
@ -71,8 +71,8 @@ SndFileSource::SndFileSource (string idstr, Flag flags)
}
}
SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
: AudioFileSource(idstr, flags, sfmt, hf)
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
: AudioFileSource (s, idstr, flags, sfmt, hf)
{
int fmt = 0;
@ -226,7 +226,6 @@ SndFileSource::open ()
_length = _info.frames;
_broadcast_info = new SF_BROADCAST_INFO;
memset (_broadcast_info, 0, sizeof (*_broadcast_info));
@ -507,6 +506,9 @@ SndFileSource::set_header_timeline_position ()
delete _broadcast_info;
_broadcast_info = 0;
}
}
jack_nframes_t

View File

@ -42,11 +42,9 @@ using std::max;
using namespace ARDOUR;
sigc::signal<void,Source*> Source::SourceCreated;
Source::Source (string name, DataType type)
: _type(type)
Source::Source (Session& s, string name, DataType type)
: _session (s)
, _type(type)
{
assert(_name.find("/") == string::npos);
@ -55,8 +53,9 @@ Source::Source (string name, DataType type)
_length = 0;
}
Source::Source (const XMLNode& node)
: _type(DataType::AUDIO)
Source::Source (Session& s, const XMLNode& node)
: _session (s)
, _type(DataType::AUDIO)
{
_timestamp = 0;
_length = 0;

View File

@ -37,7 +37,7 @@ sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
#ifdef HAVE_COREAUDIO
boost::shared_ptr<Source>
SourceFactory::create (const XMLNode& node)
SourceFactory::create (Session& s, const XMLNode& node)
{
DataType type = DataType::AUDIO;
const XMLProperty* prop = node.property("type");
@ -49,11 +49,18 @@ SourceFactory::create (const XMLNode& node)
if (node.property (X_("destructive")) != 0) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
SourceCreated (ret);
return ret;
} else {
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
SourceCreated (ret);
return ret;
} catch (failed_constructor& err) {
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (node));
@ -83,7 +90,7 @@ SourceFactory::create (const XMLNode& node)
#else
boost::shared_ptr<Source>
SourceFactory::create (const XMLNode& node)
SourceFactory::create (Session& s, const XMLNode& node)
{
DataType type = DataType::AUDIO;
const XMLProperty* prop = node.property("type");
@ -95,20 +102,20 @@ SourceFactory::create (const XMLNode& node)
if (node.property (X_("destructive")) != 0) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
SourceCreated (ret);
return ret;
} else {
boost::shared_ptr<Source> ret (new SndFileSource (node));
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
SourceCreated (ret);
return ret;
}
} else if (type == DataType::MIDI) {
boost::shared_ptr<Source> ret (new SMFSource (node));
boost::shared_ptr<Source> ret (new SMFSource (s, node));
SourceCreated (ret);
return ret;
@ -121,35 +128,34 @@ SourceFactory::create (const XMLNode& node)
#ifdef HAVE_COREAUDIO
boost::shared_ptr<Source>
SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
{
if (type == DataType::AUDIO) {
if (flags & Destructive) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (idstr, flags));
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
return ret;
}
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
return ret;
} catch (failed_constructor& err) {
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
return ret;
}
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (idstr, flags));
if (announce) {
SourceCreated (ret);
}
return ret;
}
catch (failed_constructor& err) {
boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
if (announce) {
SourceCreated (ret);
}
return ret;
}
} else if (type == DataType::MIDI) {
boost::shared_ptr<Source> ret (new SMFSource (node));
boost::shared_ptr<Source> ret (new SMFSource (s, node));
SourceCreated (ret);
return ret;
@ -161,10 +167,11 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
#else
boost::shared_ptr<Source>
SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Flag flags, bool announce)
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
{
if (type == DataType::AUDIO) {
boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
@ -172,8 +179,10 @@ SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Fla
} else if (type == DataType::MIDI) {
boost::shared_ptr<Source> ret (new SMFSource (idstr, SMFSource::Flag(0))); // FIXME: flags?
SourceCreated (ret);
boost::shared_ptr<Source> ret (new SMFSource (s, idstr, SMFSource::Flag(0))); // FIXME: flags?
if (announce) {
SourceCreated (ret);
}
return ret;
}
@ -184,13 +193,14 @@ SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Fla
#endif // HAVE_COREAUDIO
boost::shared_ptr<Source>
SourceFactory::createWritable (DataType type, std::string path, bool destructive, jack_nframes_t rate, bool announce)
SourceFactory::createWritable (DataType type, Session& s, std::string path, bool destructive, jack_nframes_t rate, bool announce)
{
/* this might throw failed_constructor(), which is OK */
if (type == DataType::AUDIO) {
if (destructive) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (path,
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
rate));
@ -200,7 +210,8 @@ SourceFactory::createWritable (DataType type, std::string path, bool destructive
return ret;
} else {
boost::shared_ptr<Source> ret (new SndFileSource (path,
boost::shared_ptr<Source> ret (new SndFileSource (s, path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
rate));
@ -208,13 +219,15 @@ SourceFactory::createWritable (DataType type, std::string path, bool destructive
SourceCreated (ret);
}
return ret;
}
} else if (type == DataType::MIDI) {
boost::shared_ptr<Source> ret (new SMFSource (path));
boost::shared_ptr<Source> ret (new SMFSource (s, path));
SourceCreated (ret);
return ret;
}
return boost::shared_ptr<Source> ();

View File

@ -919,6 +919,33 @@ jack_nframes_t
TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
{
BBT_Time the_beat;
uint32_t ticks_one_half_subdivisions_worth;
uint32_t ticks_one_subdivisions_worth;
bbt_time(fr, the_beat);
ticks_one_subdivisions_worth = (uint32_t)Meter::ticks_per_beat / sub_num;
ticks_one_half_subdivisions_worth = ticks_one_subdivisions_worth / 2;
if (the_beat.ticks % ticks_one_subdivisions_worth > ticks_one_half_subdivisions_worth) {
uint32_t difference = ticks_one_subdivisions_worth - (the_beat.ticks % ticks_one_subdivisions_worth);
if (the_beat.ticks + difference >= (uint32_t)Meter::ticks_per_beat) {
the_beat.beats++;
the_beat.ticks += difference;
the_beat.ticks -= (uint32_t)Meter::ticks_per_beat;
} else {
the_beat.ticks += difference;
}
} else {
the_beat.ticks -= the_beat.ticks % ticks_one_subdivisions_worth;
}
return frame_time (the_beat);
/* XXX just keeping this for reference
TempoMap::BBTPointList::iterator i;
TempoMap::BBTPointList *more_zoomed_bbt_points;
jack_nframes_t frame_one_beats_worth;
@ -970,6 +997,9 @@ TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
delete more_zoomed_bbt_points;
return fr ;
*/
}
jack_nframes_t

View File

@ -287,7 +287,7 @@ compute_equal_power_fades (jack_nframes_t nframes, float* in, float* out)
in[0] = 0.0f;
for (int i = 1; i < nframes - 1; ++i) {
for (jack_nframes_t i = 1; i < nframes - 1; ++i) {
in[i] = in[i-1] + step;
}

View File

@ -174,9 +174,9 @@ VSTPlugin::get_state()
if (stat (path.c_str(), &sbuf)) {
if (errno == ENOENT) {
if (mkdir (path.c_str(), 0600)) {
if (g_mkdir_with_parents (path.c_str(), 0600)) {
error << string_compose (_("cannot create VST chunk directory: %1"),
strerror (errno))
strerror (errno))
<< endmsg;
return *root;
}

View File

@ -48,6 +48,8 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
uint32_t cnt = selection->size();
uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
cerr << "lets plan to serialize " << cnt << " from selection\n";
char* buf = new char[sz];
SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
@ -59,10 +61,12 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
cnt = 0;
for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
cerr << "getting next item\n";
TreeModel::Row row = *(model->get_iter (*x));
row.get_value (data_column, sr->ptr[cnt]);
}
cerr << "returning an SR with size = " << sr->size << endl;
return sr;
}
@ -79,6 +83,7 @@ DnDTreeView::on_drag_data_get(const RefPtr<DragContext>& context, SelectionData&
SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
selection_data.set (8, (guchar*)sr, sr->size);
cerr << "selection data set to contain " << sr->size << endl;
}
}

View File

@ -42,7 +42,7 @@ class Stateful {
virtual void add_instant_xml (XMLNode&, const std::string& dir);
XMLNode *instant_xml (const std::string& str, const std::string& dir);
PBD::ID id() { return _id; }
const PBD::ID& id() const { return _id; }
protected:
XMLNode *_extra_xml;