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 () 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 # Check for liblo

View file

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

View file

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
source `dirname "$0"`/ardev_common.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'/> <menuitem action='FileHeaderFormatCAF'/>
</menu> </menu>
</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'> <menu action='Autoconnect'>
<menuitem action='AutoConnectNewTrackInputsToHardware'/> <menuitem action='AutoConnectNewTrackInputsToHardware'/>
<separator/> <separator/>

View file

@ -1651,6 +1651,9 @@ ARDOUR_UI::save_template ()
void void
ARDOUR_UI::new_session (bool startup, std::string predetermined_path) ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
{ {
string session_name;
string session_path;
int response = Gtk::RESPONSE_NONE; int response = Gtk::RESPONSE_NONE;
new_session_dialog->set_modal(true); new_session_dialog->set_modal(true);
@ -1672,14 +1675,28 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
new_session_dialog->reset(); new_session_dialog->reset();
} else if (response == Gtk::RESPONSE_YES) { } else if (response == Gtk::RESPONSE_YES) {
/* YES == OPEN, but there's no enum for that */ /* YES == OPEN, but there's no enum for that */
std::string session_name = new_session_dialog->session_name(); 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\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) { } else if (response == Gtk::RESPONSE_OK) {
if (new_session_dialog->get_current_page() == 1) { if (new_session_dialog->get_current_page() == 1) {
/* XXX this is a bit of a hack.. /* XXX this is a bit of a hack..
@ -1688,22 +1705,50 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
Unfortunately i can't see how atm.. Unfortunately i can't see how atm..
*/ */
std::string session_name = new_session_dialog->session_name(); if (session_name.empty()) {
std::string session_path = new_session_dialog->session_folder(); 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); load_session (session_path, session_name);
}
} else { } else {
_session_is_new = true; _session_is_new = true;
std::string session_name = new_session_dialog->session_name(); 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(); std::string session_path = new_session_dialog->session_folder();
}
//XXX This is needed because session constructor wants a //XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point. //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(); std::string template_name = new_session_dialog->session_template_name();
@ -1763,9 +1808,9 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
} }
} while (response == Gtk::RESPONSE_NONE); } while (response == Gtk::RESPONSE_NONE);
show(); show();
new_session_dialog->get_window()->set_cursor(); new_session_dialog->get_window()->set_cursor();
new_session_dialog->hide(); new_session_dialog->hide();
} }
@ -1873,6 +1918,11 @@ ARDOUR_UI::show ()
{ {
if (editor) { if (editor) {
editor->show_window (); editor->show_window ();
if (!shown_flag) {
editor->present ();
}
shown_flag = true; shown_flag = true;
} }

View file

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

View file

@ -131,10 +131,6 @@ ARDOUR_UI::connect_to_session (Session *s)
start_clocking (); start_clocking ();
start_blinking (); start_blinking ();
if (editor) {
editor->present();
}
transport_stopped (); transport_stopped ();
second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_second), 1000); 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::AutoReturn);
session_control_changed (Session::AutoInput); session_control_changed (Session::AutoInput);
session_control_changed (Session::Clicking); session_control_changed (Session::Clicking);
session_control_changed (Session::SmpteMode);
session->ControlChanged.connect (mem_fun (*this, &ARDOUR_UI::queue_session_control_changed)); 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: case Session::CrossfadingModel:
break; break;
case Session::AutoPlay: case Session::AutoPlay:
map_some_session_state ("Transport", "ToggleAutoPlay", &Session::get_auto_play); map_some_session_state ("Transport", "ToggleAutoPlay", &Session::get_auto_play);
break; break;

View file

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

View file

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

View file

@ -263,7 +263,7 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
GnomeCanvasSimpleRect* simplerect; GnomeCanvasSimpleRect* simplerect;
double x1, x2, y1, y2; double x1, x2, y1, y2;
double old_x1, old_x2, old_y1, old_y2; double old_x1, old_x2, old_y1, old_y2;
double a, b; double a, b, c, d;
old_x1 = item->x1; old_x1 = item->x1;
old_y1 = item->y1; old_y1 = item->y1;
@ -288,41 +288,23 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
/* now queue redraws for changed areas */ /* 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); a = MIN(item->x1, old_x1);
b = MAX(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) { a = MIN(a, item->x2);
a = MIN(a, old_x2);
b = MAX(b, item->x2);
b = MAX(b, old_x2);
/* right edge changed. redraw the area that altered */ c = MIN(item->y1, old_y1);
d = MAX(item->y1, old_y1);
a = MIN(item->x2, old_x2); c = MIN(c,item->y2);
b = MAX(item->x2, old_x2); c = MIN(c, old_y2);
gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2); d = MAX(d,item->y2);
} d = MAX(d, old_y2);
if (item->y1 != old_y1) { gnome_canvas_request_redraw (item->canvas, a, c, b + 0.5, d + 0.5);
/* 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);
}
} }
/* /*
@ -494,8 +476,8 @@ gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *c
gnome_canvas_request_redraw (item->canvas, gnome_canvas_request_redraw (item->canvas,
simplerect->bbox_ulx, simplerect->bbox_ulx,
simplerect->bbox_uly, simplerect->bbox_uly,
simplerect->bbox_lrx+1, simplerect->bbox_lrx+0.5,
simplerect->bbox_lry+1); simplerect->bbox_lry+0.5);
simplerect->full_draw_on_update = FALSE; simplerect->full_draw_on_update = FALSE;
} }

View file

@ -54,7 +54,8 @@ DISPLAYCONTROL(ShowMeasures)
DISPLAYCONTROL(ShowWaveforms) DISPLAYCONTROL(ShowWaveforms)
DISPLAYCONTROL(ShowWaveformsRecording) DISPLAYCONTROL(ShowWaveformsRecording)
IMPORTMODE(ImportAsRegion) // if this is changed, remember to update the string table in sfdb_ui.cc
IMPORTMODE(ImportAsTrack) IMPORTMODE(ImportAsRegion=0)
IMPORTMODE(ImportAsTapeTrack) IMPORTMODE(ImportToTrack=1)
IMPORTMODE(ImportToTrack) 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.pack1 (edit_packer, true, true);
edit_pane.pack2 (the_notebook, false, 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); 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::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false));
ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true)); ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true));
ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll)); ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
constructed = true; constructed = true;
instant_save (); instant_save ();
@ -882,6 +883,9 @@ Editor::reposition_x_origin (jack_nframes_t frame)
} }
horizontal_adjustment.set_value (frame/frames_per_unit); horizontal_adjustment.set_value (frame/frames_per_unit);
} else {
update_fixed_rulers();
tempo_map_changed (Change (0));
} }
} }
@ -963,22 +967,12 @@ Editor::deferred_control_scroll (jack_nframes_t target)
void void
Editor::canvas_horizontally_scrolled () 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 (); update_fixed_rulers ();
tempo_map_changed (Change (0)); tempo_map_changed (Change (0));
return false;
} }
void void
@ -996,7 +990,6 @@ Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
set_frames_per_unit (nfpu); set_frames_per_unit (nfpu);
reposition_x_origin (frame); reposition_x_origin (frame);
repos_zoom_queued = false; repos_zoom_queued = false;
return FALSE; return FALSE;
@ -1033,6 +1026,10 @@ Editor::session_control_changed (Session::ControlType t)
update_layering_model (); update_layering_model ();
break; break;
case Session::SmpteMode:
update_smpte_mode ();
break;
default: default:
break; 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->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_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))); session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
edit_groups_changed (); edit_groups_changed ();
@ -1267,8 +1267,11 @@ Editor::connect_to_session (Session *t)
/* xfade visibility state set from editor::set_state() */ /* xfade visibility state set from editor::set_state() */
update_crossfade_model (); update_crossfade_model();
update_layering_model (); update_layering_model();
update_smpte_mode();
update_video_pullup();
handle_new_duration (); handle_new_duration ();
@ -1292,7 +1295,7 @@ Editor::connect_to_session (Session *t)
horizontal_adjustment.set_value (0); horizontal_adjustment.set_value (0);
restore_ruler_visibility (); restore_ruler_visibility ();
tempo_map_changed (Change (0)); //tempo_map_changed (Change (0));
session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
edit_cursor->set_position (0); edit_cursor->set_position (0);
@ -1328,6 +1331,7 @@ Editor::connect_to_session (Session *t)
} }
/* register for undo history */ /* register for undo history */
session->register_with_memento_command_factory(_id, this); session->register_with_memento_command_factory(_id, this);
} }
@ -2110,6 +2114,9 @@ Editor::set_state (const XMLNode& node)
int x, y, xoff, yoff; int x, y, xoff, yoff;
Gdk::Geometry g; Gdk::Geometry g;
if ((prop = node.property ("id")) != 0) {
_id = prop->value ();
}
if ((geometry = find_named_node (node, "geometry")) == 0) { if ((geometry = find_named_node (node, "geometry")) == 0) {
@ -2241,6 +2248,9 @@ Editor::get_state ()
XMLNode* node = new XMLNode ("Editor"); XMLNode* node = new XMLNode ("Editor");
char buf[32]; char buf[32];
_id.print (buf);
node->add_property ("id", buf);
if (is_realized()) { if (is_realized()) {
Glib::RefPtr<Gdk::Window> win = get_window(); Glib::RefPtr<Gdk::Window> win = get_window();
@ -2250,7 +2260,7 @@ Editor::get_state ()
win->get_size(width, height); win->get_size(width, height);
XMLNode* geometry = new XMLNode ("geometry"); XMLNode* geometry = new XMLNode ("geometry");
char buf[32];
snprintf(buf, sizeof(buf), "%d", width); snprintf(buf, sizeof(buf), "%d", width);
geometry->add_property("x_size", string(buf)); geometry->add_property("x_size", string(buf));
snprintf(buf, sizeof(buf), "%d", height); snprintf(buf, sizeof(buf), "%d", height);
@ -4085,6 +4095,7 @@ Editor::restore_editing_space ()
{ {
mouse_mode_tearoff->set_visible (true); mouse_mode_tearoff->set_visible (true);
tools_tearoff->set_visible (true); tools_tearoff->set_visible (true);
edit_pane.set_position (pre_maximal_pane_position); edit_pane.set_position (pre_maximal_pane_position);
unfullscreen(); unfullscreen();
@ -4138,6 +4149,87 @@ Editor::on_key_press_event (GdkEventKey* ev)
return key_press_focus_accelerator_handler (*this, 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 void
Editor::update_layering_model () Editor::update_layering_model ()
{ {
@ -4163,7 +4255,6 @@ Editor::update_layering_model ()
} }
} }
void void
Editor::update_crossfade_model () Editor::update_crossfade_model ()
{ {

View file

@ -143,8 +143,6 @@ class Editor : public PublicEditor
XMLNode& get_state (); XMLNode& get_state ();
int set_state (const XMLNode& ); int set_state (const XMLNode& );
PBD::ID id() { return _id; }
void set_mouse_mode (Editing::MouseMode, bool force=true); void set_mouse_mode (Editing::MouseMode, bool force=true);
void step_mouse_mode (bool next); void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () { return mouse_mode; } Editing::MouseMode current_mouse_mode () { return mouse_mode; }
@ -231,6 +229,7 @@ class Editor : public PublicEditor
void set_show_measures (bool yn); void set_show_measures (bool yn);
bool show_measures () const { return _show_measures; } bool show_measures () const { return _show_measures; }
bool initial_ruler_update_required;
#ifdef FFT_ANALYSIS #ifdef FFT_ANALYSIS
/* analysis window */ /* analysis window */
@ -302,6 +301,14 @@ class Editor : public PublicEditor
void set_meter_falloff (int); void set_meter_falloff (int);
void set_meter_hold (int32_t); 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 */ /* xfades */
void toggle_auto_xfade (); void toggle_auto_xfade ();
@ -311,8 +318,8 @@ class Editor : public PublicEditor
void update_crossfade_model (); void update_crossfade_model ();
void set_crossfade_model (ARDOUR::CrossfadeModel); void set_crossfade_model (ARDOUR::CrossfadeModel);
/* layers */
/* layers */
void set_layer_model (ARDOUR::Session::LayerModel); void set_layer_model (ARDOUR::Session::LayerModel);
void update_layering_model (); void update_layering_model ();
@ -349,8 +356,6 @@ class Editor : public PublicEditor
ARDOUR::AudioEngine& engine; ARDOUR::AudioEngine& engine;
bool constructed; bool constructed;
PBD::ID _id;
PlaylistSelector* _playlist_selector; PlaylistSelector* _playlist_selector;
void set_frames_per_unit (double); void set_frames_per_unit (double);
@ -683,7 +688,7 @@ class Editor : public PublicEditor
void tie_vertical_scrolling (); void tie_vertical_scrolling ();
void canvas_horizontally_scrolled (); void canvas_horizontally_scrolled ();
bool lazy_canvas_horizontally_scrolled ();
void reposition_and_zoom (jack_nframes_t sample, double fpu); void reposition_and_zoom (jack_nframes_t sample, double fpu);
gint deferred_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*); void end_location_changed (ARDOUR::Location*);
@ -1185,8 +1190,6 @@ class Editor : public PublicEditor
bool _follow_playhead; bool _follow_playhead;
bool _show_waveforms_recording; bool _show_waveforms_recording;
void add_bbt_marks (ARDOUR::TempoMap::BBTPointList&);
ARDOUR::TempoMap::BBTPointList *current_bbt_points; ARDOUR::TempoMap::BBTPointList *current_bbt_points;
typedef vector<ArdourCanvas::SimpleLine*> TimeLineList; typedef vector<ArdourCanvas::SimpleLine*> TimeLineList;
@ -1197,7 +1200,7 @@ class Editor : public PublicEditor
ArdourCanvas::SimpleLine* get_time_line (); ArdourCanvas::SimpleLine* get_time_line ();
void hide_measures (); void hide_measures ();
void draw_measures (); void draw_measures ();
void draw_time_bars (); bool lazy_hide_and_draw_measures ();
void new_tempo_section (); void new_tempo_section ();
@ -1506,7 +1509,7 @@ class Editor : public PublicEditor
jack_nframes_t autoscroll_distance; jack_nframes_t autoscroll_distance;
static gint _autoscroll_canvas (void *); static gint _autoscroll_canvas (void *);
gint autoscroll_canvas (); bool autoscroll_canvas ();
void start_canvas_autoscroll (int direction); void start_canvas_autoscroll (int direction);
void stop_canvas_autoscroll (); void stop_canvas_autoscroll ();
void maybe_autoscroll (GdkEvent*); 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_("Monitoring"), _("Monitoring"));
ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect")); ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect"));
ActionManager::register_action (editor_actions, X_("Layering"), _("Layering")); ActionManager::register_action (editor_actions, X_("Layering"), _("Layering"));
ActionManager::register_action (editor_actions, X_("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_("Metering"), _("Metering"));
ActionManager::register_action (editor_actions, X_("MeteringFallOffRate"), _("Fall off rate")); ActionManager::register_action (editor_actions, X_("MeteringFallOffRate"), _("Fall off rate"));
ActionManager::register_action (editor_actions, X_("MeteringHoldTime"), _("Hold Time")); 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_("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)); 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 (rl_actions);
ActionManager::add_action_group (zoom_actions); ActionManager::add_action_group (zoom_actions);
ActionManager::add_action_group (mouse_mode_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 void
Editor::set_crossfade_model (CrossfadeModel model) 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); idspec += string_compose(":%1", n);
try { 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); sources.push_back(source);
} }

View file

@ -267,13 +267,14 @@ Editor::initialize_canvas ()
edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event); edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event);
playhead_cursor = new Cursor (*this, "red", &Editor::canvas_playhead_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)); track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
} }
void void
Editor::track_canvas_allocate (Gtk::Allocation alloc) Editor::track_canvas_allocate (Gtk::Allocation alloc)
{ {
static bool first_time = true;
canvas_width = alloc.get_width(); canvas_width = alloc.get_width();
canvas_height = alloc.get_height(); canvas_height = alloc.get_height();
@ -318,13 +319,15 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
transport_punchout_line->property_y2() = canvas_height; transport_punchout_line->property_y2() = canvas_height;
} }
update_fixed_rulers (); if (is_visible() && initial_ruler_update_required) {
/*
if (is_visible() && first_time) { 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)); tempo_map_changed (Change (0));
first_time = false; initial_ruler_update_required = false;
} else {
redisplay_tempo ();
} }
Resized (); /* EMIT_SIGNAL */ Resized (); /* EMIT_SIGNAL */
@ -414,6 +417,8 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
const SelectionData& data, const SelectionData& data,
guint info, guint time) guint info, guint time)
{ {
cerr << "dropping, target = " << data.get_target() << endl;
if (data.get_target() == "regions") { if (data.get_target() == "regions") {
drop_regions (context, x, y, data, info, time); drop_regions (context, x, y, data, info, time);
} else { } 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 (); stop_canvas_autoscroll ();
} }
@ -545,11 +550,10 @@ Editor::_autoscroll_canvas (void *arg)
return ((Editor *) arg)->autoscroll_canvas (); return ((Editor *) arg)->autoscroll_canvas ();
} }
gint bool
Editor::autoscroll_canvas () Editor::autoscroll_canvas ()
{ {
jack_nframes_t new_frame; jack_nframes_t new_frame;
bool keep_calling = true;
jack_nframes_t limit = max_frames - current_page_frames(); jack_nframes_t limit = max_frames - current_page_frames();
GdkEventMotion ev; GdkEventMotion ev;
jack_nframes_t target_frame; jack_nframes_t target_frame;
@ -570,10 +574,6 @@ Editor::autoscroll_canvas ()
target_frame = drag_info.current_pointer_frame + autoscroll_distance; 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 */ /* now fake a motion event to get the object that is being dragged to move too */
ev.type = GDK_MOTION_NOTIFY; ev.type = GDK_MOTION_NOTIFY;
@ -593,20 +593,26 @@ Editor::autoscroll_canvas ()
/* connect the timeout so that we get called repeatedly */ /* connect the timeout so that we get called repeatedly */
autoscroll_timeout_tag = g_timeout_add (20, _autoscroll_canvas, this); autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
keep_calling = false; 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 */ /* 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); 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 */ /* 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 void

View file

@ -210,7 +210,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
try { 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) { catch (failed_constructor& err) {
@ -343,7 +343,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
path = s; path = s;
try { 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) { catch (failed_constructor& err) {

View file

@ -1110,9 +1110,9 @@ Editor::temporal_zoom_step (bool coarser)
nfpu = frames_per_unit; nfpu = frames_per_unit;
if (coarser) { if (coarser) {
nfpu *= 2.0; nfpu *= 1.61803399;
} else { } else {
nfpu = max(1.0,(nfpu/2.0)); nfpu = max(1.0,(nfpu/1.61803399));
} }
temporal_zoom (nfpu); temporal_zoom (nfpu);
@ -1251,22 +1251,22 @@ Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
{ {
if (!session) return; if (!session) return;
jack_nframes_t range_before = frame - leftmost_frame; double range_before = frame - leftmost_frame;
double new_fpu; double new_fpu;
new_fpu = frames_per_unit; new_fpu = frames_per_unit;
if (coarser) { if (coarser) {
new_fpu *= 2.0; new_fpu *= 1.61803399;
range_before *= 2; range_before *= 1.61803399;
} else { } else {
new_fpu = max(1.0,(new_fpu/2.0)); new_fpu = max(1.0,(new_fpu/1.61803399));
range_before /= 2; range_before /= 1.61803399;
} }
if (new_fpu == frames_per_unit) return; 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; 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 ()))) { if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
lower = lower - spacer; lower = lower - spacer;
} else { } else {
upper = upper + spacer - lower;
lower = 0; lower = 0;
} }
upper = upper + spacer;
range = (jack_nframes_t) floor (upper - lower); range = (jack_nframes_t) floor (upper - lower);
if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */ if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
@ -1036,113 +1036,86 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
} }
TempoMap::BBTPointList::iterator i; TempoMap::BBTPointList::iterator i;
TempoMap::BBTPointList *zoomed_bbt_points;
uint32_t beats = 0; uint32_t beats = 0;
uint32_t bars = 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 desirable_marks;
uint32_t magic_accent_number = 1; uint32_t magic_accent_number = 1;
gint nmarks; gint nmarks;
char buf[64]; char buf[64];
gint n; gint n;
jack_nframes_t pos; 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; BBT_Time next_beat;
jack_nframes_t next_beat_pos; jack_nframes_t next_beat_pos;
jack_nframes_t ilower = (jack_nframes_t) floor (lower); 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; return 0;
} }
/* align the tick marks to whatever we're snapping to... */ /* align the tick marks to whatever we're snapping to... */
if (snap_type == SnapToAThirdBeat) { switch (snap_type) {
case SnapToAThirdBeat:
bbt_beat_subdivision = 3; bbt_beat_subdivision = 3;
} else if (snap_type == SnapToAQuarterBeat) { break;
case SnapToAQuarterBeat:
bbt_beat_subdivision = 4; bbt_beat_subdivision = 4;
} else if (snap_type == SnapToAEighthBeat) { break;
case SnapToAEighthBeat:
bbt_beat_subdivision = 8; bbt_beat_subdivision = 8;
magic_accent_number = 2; magic_accent_number = 2;
} else if (snap_type == SnapToASixteenthBeat) { break;
case SnapToASixteenthBeat:
bbt_beat_subdivision = 16; bbt_beat_subdivision = 16;
magic_accent_number = 4; magic_accent_number = 4;
} else if (snap_type == SnapToAThirtysecondBeat) { break;
case SnapToAThirtysecondBeat:
bbt_beat_subdivision = 32; bbt_beat_subdivision = 32;
magic_accent_number = 8; magic_accent_number = 8;
} else { break;
default:
bbt_beat_subdivision = 4; 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 */ if (current_bbt_points == 0 || current_bbt_points->empty()) {
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()) {
return 0; return 0;
} }
for (i = current_bbt_points->begin(); i != current_bbt_points->end(); i++) { i = current_bbt_points->end();
if ((*i).type == TempoMap::Beat) { i--;
beats++; bars = (*i).bar - (*current_bbt_points->begin()).bar;
} else if ((*i).type == TempoMap::Bar) { beats = current_bbt_points->size() - bars;
bars++;
}
}
/*Only show the bar helper if there aren't many bars on the screen */
if (bars > 1) {
bar_helper_on = false;
}
for (i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end(); i++) { /*Only show the bar helper if there aren't many bars on the screen */
if ((*i).type == TempoMap::Beat) { if (bars > 2) {
zoomed_beats++; bar_helper_on = false;
} else if ((*i).type == TempoMap::Bar) {
zoomed_bars++;
}
} }
if (desirable_marks > (beats / 4)) { if (desirable_marks > (beats / 4)) {
/* we're in beat land...*/ /* 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; double position_of_helper;
bool i_am_accented = false; bool i_am_accented = false;
bool we_need_ticks = false; bool we_need_ticks = false;
position_of_helper = ilower + (30 * Editor::get_current_zoom ()); position_of_helper = ilower + (30 * Editor::get_current_zoom ());
if (desirable_marks >= (beats * 2)) { if (desirable_marks >= (beats)) {
nmarks = (zoomed_beats * bbt_beat_subdivision) + 1; nmarks = ((beats + 1) * bbt_beat_subdivision) + 1;
we_need_ticks = true; we_need_ticks = true;
} else { } else {
nmarks = zoomed_beats + 1; nmarks = beats + 1;
} }
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); *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].position = ilower;
(*marks)[0].style = GtkCustomRulerMarkMicro; (*marks)[0].style = GtkCustomRulerMarkMicro;
for (n = 1, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) { for (n = 1, i = current_bbt_points->begin(); n < nmarks && i != current_bbt_points->end(); i++) {
if ((*i).frame <= ilower && (bar_helper_on)) {
if ((*i).frame < ilower && (bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat); snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
(*marks)[0].label = g_strdup (buf); (*marks)[0].label = g_strdup (buf);
} else { } else {
if ((*i).type == TempoMap::Bar) { if ((*i).type == TempoMap::Bar) {
tick = 0;
(((*i).frame < position_of_helper) && bar_helper_on) ? (((*i).frame < position_of_helper) && bar_helper_on) ?
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
(*marks)[n].label = g_strdup (buf); (*marks)[n].label = g_strdup (buf);
@ -1170,7 +1140,6 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
n++; n++;
} else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) { } else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
tick = 0;
((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ? ((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ?
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat); snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
if (((*i).beat % 2 == 1) || we_need_ticks) { if (((*i).beat % 2 == 1) || we_need_ticks) {
@ -1184,11 +1153,18 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
} }
} }
/* Add the tick marks */
if (we_need_ticks && (*i).type != TempoMap::Bar) {
/* Find the next beat */ /* Find the next beat */
session->bbt_time((*i).frame, next_beat); next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
if (session->tempo_map().meter_at((*i).frame).beats_per_bar() > (next_beat.beats + 1)) { if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1; next_beat.beats += 1;
} else { } else {
next_beat.bars += 1; next_beat.bars += 1;
@ -1197,20 +1173,16 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
next_beat_pos = session->tempo_map().frame_time(next_beat); next_beat_pos = session->tempo_map().frame_time(next_beat);
/* Add the tick marks */ 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;
if (we_need_ticks) {
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;
skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision); skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
pos = (*i).frame + frame_skip; pos = (*i).frame + frame_skip;
accumulated_error = frame_skip_error; 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)) { if (t % magic_accent_number == (magic_accent_number - 1)) {
i_am_accented = true; 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 return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures
} else { } else {
/* we're in bar land */ /* we're in bar land */
if (desirable_marks < (uint32_t) (zoomed_bars / 256)) { if (desirable_marks < (uint32_t) (bars / 256)) {
nmarks = 1; nmarks = 1;
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); *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].style = GtkCustomRulerMarkMajor;
(*marks)[0].label = g_strdup (buf); (*marks)[0].label = g_strdup (buf);
(*marks)[0].position = ilower; (*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); *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).type == TempoMap::Bar) {
if ((*i).bar % 64 == 1) { if ((*i).bar % 64 == 1) {
if ((*i).bar % 256 == 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); *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).type == TempoMap::Bar) {
if ((*i).bar % 16 == 1) { if ((*i).bar % 16 == 1) {
if ((*i).bar % 64 == 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); *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).type == TempoMap::Bar) {
if ((*i).bar % 4 == 1) { if ((*i).bar % 4 == 1) {
if ((*i).bar % 16 == 1) { if ((*i).bar % 16 == 1) {
@ -1328,9 +1299,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
} }
} }
} else { } else {
nmarks = zoomed_bars; nmarks = bars;
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); *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).type == TempoMap::Bar) {
if ((*i).bar % 4 == 1) { if ((*i).bar % 4 == 1) {
snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); 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; 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 ()))) { if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
lower = lower - spacer; lower = lower - spacer;
} else { } else {
upper = upper + spacer;
lower = 0; lower = 0;
} }
upper = upper + spacer;
range = iupper - ilower; range = iupper - ilower;
if (range < (fr / 50)) { if (range < (fr / 50)) {

View file

@ -97,13 +97,35 @@ Editor::tempo_map_changed (Change ignored)
{ {
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::tempo_map_changed), 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) { if (current_bbt_points) {
delete current_bbt_points; delete current_bbt_points;
current_bbt_points = 0; current_bbt_points = 0;
} }
if (session) { 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 { } else {
current_bbt_points = 0; current_bbt_points = 0;
} }
@ -114,11 +136,11 @@ Editor::tempo_map_changed (Change ignored)
void void
Editor::redisplay_tempo () Editor::redisplay_tempo ()
{ {
hide_measures ();
if (session && current_bbt_points) { if (session && current_bbt_points) {
draw_measures (); Glib::signal_idle().connect (mem_fun (*this, &Editor::lazy_hide_and_draw_measures));
update_tempo_based_rulers (); } else {
hide_measures ();
} }
} }
@ -149,6 +171,14 @@ Editor::get_time_line ()
return line; return line;
} }
bool
Editor::lazy_hide_and_draw_measures ()
{
hide_measures ();
draw_measures ();
return false;
}
void void
Editor::draw_measures () Editor::draw_measures ()
{ {
@ -156,86 +186,63 @@ Editor::draw_measures ()
return; return;
} }
TempoMap::BBTPointList::iterator i = current_bbt_points->begin(); TempoMap::BBTPointList::iterator i;
TempoMap::BBTPoint& p = (*i);
ArdourCanvas::SimpleLine *line; ArdourCanvas::SimpleLine *line;
gdouble xpos, last_xpos; gdouble xpos;
uint32_t cnt; double x1, x2, y1, y2, beat_density;
uint32_t beats = 0;
uint32_t bars = 0;
uint32_t color; uint32_t color;
if (current_bbt_points == 0 || current_bbt_points->empty()) { if (current_bbt_points == 0 || current_bbt_points->empty()) {
return; return;
} }
cnt = 0; track_canvas.get_scroll_region (x1, y1, x2, y2);
last_xpos = 0;
/* get the first bar spacing */ /* get the first bar spacing */
gdouble last_beat = DBL_MAX; i = current_bbt_points->end();
gdouble beat_spacing = 0; 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) { beat_density = (beats * 10.0f) / track_canvas.get_width ();
TempoMap::BBTPoint& p = (*i);
switch (p.type) { if (beat_density > 2.0f) {
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 the lines are too close together, they become useless */
return; 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) { for (i = current_bbt_points->begin(); i != current_bbt_points->end(); ++i) {
p = (*i); switch ((*i).type) {
switch (p.type) {
case TempoMap::Bar: case TempoMap::Bar:
break; break;
case TempoMap::Beat: case TempoMap::Beat:
xpos = frame_to_unit (p.frame);
if (p.beat == 1) { if ((*i).beat == 1) {
color = color_map[cMeasureLineBeat]; color = color_map[cMeasureLineBeat];
} else { } else {
color = color_map[cMeasureLineBar]; color = color_map[cMeasureLineBar];
/* only draw beat lines if the gaps between beats /* only draw beat lines if the gaps between beats are large. */
are large.
*/
if (beat_spacing < 4.0) { if (beat_density > 0.25) {
break; break;
} }
} }
if (cnt == 0 || xpos - last_xpos > 4.0) { xpos = frame_to_unit ((*i).frame);
line = get_time_line (); line = get_time_line ();
line->property_x1() = xpos; line->property_x1() = xpos;
line->property_x2() = xpos; line->property_x2() = xpos;
line->property_y2() = y2; line->property_y2() = y2;
line->property_color_rgba() = color; line->property_color_rgba() = color;
line->raise_to_top(); //line->raise_to_top();
line->show(); line->show();
last_xpos = xpos;
++cnt;
}
break; break;
} }
} }
@ -244,6 +251,7 @@ Editor::draw_measures ()
cursor_group->raise_to_top(); cursor_group->raise_to_top();
time_line_group->lower_to_bottom(); time_line_group->lower_to_bottom();
return;
} }
void void

View file

@ -183,8 +183,8 @@ MidiStreamView::setup_rec_box ()
assert(region); assert(region);
region->set_position (_trackview.session().transport_frame(), this); region->set_position (_trackview.session().transport_frame(), this);
rec_regions.push_back (region); 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 */ /* we add the region later */
} }
@ -252,6 +252,15 @@ MidiStreamView::setup_rec_box ()
last_rec_data_frame = 0; last_rec_data_frame = 0;
/* remove temp regions */ /* 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(); rec_regions.clear();
// cerr << "\tclear " << rec_rects.size() << " rec rects\n"; // cerr << "\tclear " << rec_rects.size() << " rec rects\n";

View file

@ -699,7 +699,7 @@ NewSessionDialog::reset_recent()
row[recent_columns.visible_name] = Glib::path_get_basename (fullpath); row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
row[recent_columns.fullpath] = fullpath; row[recent_columns.fullpath] = fullpath;
if (states->size() > 1) { if (states->size()) {
/* add the children */ /* add the children */

View file

@ -152,7 +152,6 @@ OptionEditor::set_session (Session *s)
click_emphasis_path_entry.set_sensitive (false); click_emphasis_path_entry.set_sensitive (false);
session_raid_entry.set_sensitive (false); session_raid_entry.set_sensitive (false);
smpte_fps_combo.set_sensitive (false);
short_xfade_slider.set_sensitive (false); short_xfade_slider.set_sensitive (false);
smpte_offset_negative_button.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_path_entry.set_sensitive (true);
click_emphasis_path_entry.set_sensitive (true); click_emphasis_path_entry.set_sensitive (true);
session_raid_entry.set_sensitive (true); session_raid_entry.set_sensitive (true);
smpte_fps_combo.set_sensitive (true);
short_xfade_slider.set_sensitive (true); short_xfade_slider.set_sensitive (true);
smpte_offset_negative_button.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_session (s);
smpte_offset_clock.set (s->smpte_offset (), true); smpte_offset_clock.set (s->smpte_offset (), true);
@ -352,15 +332,6 @@ OptionEditor::setup_sync_options ()
HBox* hbox; HBox* hbox;
vector<string> dumb; 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.set_mode (AudioClock::SMPTE);
smpte_offset_clock.ValueChanged.connect (mem_fun(*this, &OptionEditor::smpte_offset_chosen)); 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); 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"))); Label *smpte_offset_label = manage (new Label (_("SMPTE Offset")));
smpte_fps_label->set_name("OptionsLabel");
smpte_offset_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 = manage (new HBox);
hbox->set_border_width (5); hbox->set_border_width (5);
hbox->set_spacing (10); 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 void
OptionEditor::smpte_offset_chosen() OptionEditor::smpte_offset_chosen()
{ {

View file

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

View file

@ -26,16 +26,12 @@ class AudioRegionGainLine : public AutomationLine
void remove_point (ControlPoint&); void remove_point (ControlPoint&);
PBD::ID id() { return _id; }
private: private:
ARDOUR::Session& session; ARDOUR::Session& session;
AudioRegionView& rv; AudioRegionView& rv;
UndoAction get_memento(); 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"))))); 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); 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)); playlist_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::playlist_click));
automation_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::automation_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)); visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click));
hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_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()) { if (is_track()) {
rec_enable_button->set_active (false); rec_enable_button->set_active (false);
rec_enable_button->set_name ("TrackRecordEnableButton"); 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)); 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); 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")); 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->name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
if (is_track()) { if (is_track()) {
track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen)); 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)); editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler)); ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler));
} }
RouteTimeAxisView::~RouteTimeAxisView () RouteTimeAxisView::~RouteTimeAxisView ()
@ -605,19 +599,19 @@ RouteTimeAxisView::set_height (TrackHeight h)
show_name_entry (); show_name_entry ();
hide_name_label (); hide_name_label ();
mute_button->show_all(); mute_button->show();
solo_button->show_all(); solo_button->show();
if (rec_enable_button) if (rec_enable_button)
rec_enable_button->show_all(); rec_enable_button->show();
edit_group_button.show_all(); edit_group_button.show();
hide_button.show_all(); hide_button.show();
visual_button.show_all(); visual_button.show();
size_button.show_all(); size_button.show();
automation_button.show_all(); automation_button.show();
if (is_track() && track()->mode() == ARDOUR::Normal) { if (is_track() && track()->mode() == ARDOUR::Normal) {
playlist_button.show_all(); playlist_button.show();
} }
break; break;
@ -625,10 +619,10 @@ RouteTimeAxisView::set_height (TrackHeight h)
show_name_entry (); show_name_entry ();
hide_name_label (); hide_name_label ();
mute_button->show_all(); mute_button->show();
solo_button->show_all(); solo_button->show();
if (rec_enable_button) if (rec_enable_button)
rec_enable_button->show_all(); rec_enable_button->show();
edit_group_button.hide (); edit_group_button.hide ();
hide_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 void
RouteTimeAxisView::show_all_automation () RouteTimeAxisView::show_all_automation ()
{ {

View file

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

View file

@ -100,7 +100,7 @@ RouteUI::~RouteUI()
delete mute_menu; delete mute_menu;
} }
gint bool
RouteUI::mute_press(GdkEventButton* ev) RouteUI::mute_press(GdkEventButton* ev)
{ {
if (!ignore_toggle) { if (!ignore_toggle) {
@ -161,7 +161,7 @@ RouteUI::mute_press(GdkEventButton* ev)
return true; return true;
} }
gint bool
RouteUI::mute_release(GdkEventButton* ev) RouteUI::mute_release(GdkEventButton* ev)
{ {
if (!ignore_toggle) { if (!ignore_toggle) {
@ -175,7 +175,7 @@ RouteUI::mute_release(GdkEventButton* ev)
return true; return true;
} }
gint bool
RouteUI::solo_press(GdkEventButton* ev) RouteUI::solo_press(GdkEventButton* ev)
{ {
if (!ignore_toggle) { if (!ignore_toggle) {
@ -255,7 +255,7 @@ RouteUI::solo_press(GdkEventButton* ev)
return true; return true;
} }
gint bool
RouteUI::solo_release(GdkEventButton* ev) RouteUI::solo_release(GdkEventButton* ev)
{ {
if (!ignore_toggle) { if (!ignore_toggle) {
@ -271,7 +271,7 @@ RouteUI::solo_release(GdkEventButton* ev)
return true; return true;
} }
gint bool
RouteUI::rec_enable_press(GdkEventButton* ev) RouteUI::rec_enable_press(GdkEventButton* ev)
{ {
if (!ignore_toggle && is_track() && rec_enable_button) { 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); XMLNode* get_child_xml_node (const string & childname);
gint mute_press(GdkEventButton*); bool mute_press(GdkEventButton*);
gint mute_release(GdkEventButton*); bool mute_release(GdkEventButton*);
gint solo_press(GdkEventButton*); bool solo_press(GdkEventButton*);
gint solo_release(GdkEventButton*); bool solo_release(GdkEventButton*);
gint rec_enable_press(GdkEventButton*); bool rec_enable_press(GdkEventButton*);
void solo_changed(void*); void solo_changed(void*);
void mute_changed(void*); void mute_changed(void*);

View file

@ -36,6 +36,7 @@
#include <ardour/source_factory.h> #include <ardour/source_factory.h>
#include "ardour_ui.h" #include "ardour_ui.h"
#include "editing.h"
#include "gui_thread.h" #include "gui_thread.h"
#include "prompter.h" #include "prompter.h"
#include "sfdb_ui.h" #include "sfdb_ui.h"
@ -197,7 +198,7 @@ SoundFileBox::play_btn_clicked ()
for (int n = 0; n < sf_info.channels; ++n) { for (int n = 0; n < sf_info.channels; ++n) {
try { 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); srclist.push_back(afs);
} catch (failed_constructor& err) { } 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) SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
: ArdourDialog (title, false), : ArdourDialog (title, false),
chooser (Gtk::FILE_CHOOSER_ACTION_OPEN) chooser (Gtk::FILE_CHOOSER_ACTION_OPEN)
@ -339,13 +349,6 @@ SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
show_all (); 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; vector<string> SoundFileOmega::mode_strings;
SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s) 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 void
StreamView::remove_rec_region (boost::shared_ptr<Region> r) StreamView::remove_rec_region (boost::shared_ptr<Region> r)
{ {
@ -195,6 +197,7 @@ StreamView::remove_rec_region (boost::shared_ptr<Region> r)
} }
} }
} }
#endif
void void
StreamView::undisplay_diskstream () 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 add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves) = 0;
virtual void remove_region_view (boost::shared_ptr<ARDOUR::Region> ); 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>); void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void undisplay_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) context.Result(result)
return 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 = { conf = Configure(ardour, custom_tests = {
'CheckJackClientOpen' : CheckJackClientOpen, 'CheckJackClientOpen' : CheckJackClientOpen,
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies 'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset
}) })
if conf.CheckJackClientOpen(): if conf.CheckJackClientOpen():
@ -182,6 +200,14 @@ if conf.CheckJackClientOpen():
if conf.CheckJackRecomputeLatencies(): if conf.CheckJackRecomputeLatencies():
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES") 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 # Optional header files
# #

View file

@ -61,8 +61,6 @@ class AudioDiskstream : public Diskstream
AudioDiskstream (Session &, const XMLNode&); AudioDiskstream (Session &, const XMLNode&);
~AudioDiskstream(); ~AudioDiskstream();
const PBD::ID& id() const { return _id; }
float playback_buffer_load() const; float playback_buffer_load() const;
float capture_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); 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_streaming_write_completed ();
void mark_take (string); void mark_take (string);
@ -104,16 +104,16 @@ class AudioFileSource : public AudioSource {
/* constructor to be called for existing external-to-session files */ /* 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 */ /* 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); SampleFormat samp_format, HeaderFormat hdr_format);
/* constructor to be called for existing in-session files */ /* constructor to be called for existing in-session files */
AudioFileSource (const XMLNode&); AudioFileSource (Session&, const XMLNode&);
int init (string idstr, bool must_exist); int init (string idstr, bool must_exist);
@ -121,7 +121,6 @@ class AudioFileSource : public AudioSource {
string _path; string _path;
Flag _flags; Flag _flags;
string _take_id; string _take_id;
bool allow_remove_if_empty;
uint64_t timeline_position; uint64_t timeline_position;
static string peak_dir; static string peak_dir;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -31,12 +31,12 @@ namespace ARDOUR {
class DestructiveFileSource : public SndFileSource { class DestructiveFileSource : public SndFileSource {
public: 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)); 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 (); ~DestructiveFileSource ();
jack_nframes_t last_capture_start_frame() const; jack_nframes_t last_capture_start_frame() const;

View file

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

View file

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

View file

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

View file

@ -43,8 +43,8 @@ class MidiRingBuffer;
class MidiSource : public Source class MidiSource : public Source
{ {
public: public:
MidiSource (string name); MidiSource (Session& session, string name);
MidiSource (const XMLNode&); MidiSource (Session& session, const XMLNode&);
virtual ~MidiSource (); virtual ~MidiSource ();
virtual jack_nframes_t read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const; 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; } EditMode get_edit_mode() const { return _edit_mode; }
void set_edit_mode (EditMode); void set_edit_mode (EditMode);
PBD::ID id() { return _id; }
/* Editing operations */ /* Editing operations */
void add_region (boost::shared_ptr<Region>, jack_nframes_t position, float times = 1, bool with_save = true); 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 unset_freeze_child (Playlist*);
void timestamp_layer_op (boost::shared_ptr<Region>); void timestamp_layer_op (boost::shared_ptr<Region>);
PBD::ID _id;
}; };
} /* namespace ARDOUR */ } /* namespace ARDOUR */

View file

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

View file

@ -37,7 +37,6 @@ class XMLNode;
namespace ARDOUR { namespace ARDOUR {
class Playlist; class Playlist;
class Source;
enum RegionEditState { enum RegionEditState {
EditChangesNothing = 0, EditChangesNothing = 0,
@ -99,8 +98,6 @@ class Region : public PBD::StatefulDestructible, public StateManager, public boo
virtual ~Region(); virtual ~Region();
const PBD::ID& id() const { return _id; }
/* Note: changing the name of a Region does not constitute an edit */ /* Note: changing the name of a Region does not constitute an edit */
string name() const { return _name; } 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; } bool dirty() const { return _state_of_the_state & Dirty; }
sigc::signal<void> DirtyChanged; sigc::signal<void> DirtyChanged;
std::string sound_dir () const; std::string sound_dir (bool with_path = true) const;
std::string tape_dir () const;
std::string peak_dir () const; std::string peak_dir () const;
std::string dead_sound_dir () const; std::string dead_sound_dir () const;
std::string automation_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_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 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 audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
string midi_path_from_name (string); string midi_path_from_name (string);
@ -1713,9 +1713,10 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
uint32_t _total_free_4k_blocks; uint32_t _total_free_4k_blocks;
Glib::Mutex space_lock; Glib::Mutex space_lock;
static const char* old_sound_dir_name;
static const char* 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* dead_sound_dir_name;
static const char* interchange_dir_name;
static const char* peak_dir_name; static const char* peak_dir_name;
string discover_best_sound_dir (bool destructive = false); 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 */ /** 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 */ /* Constructor for existing in-session files */
SMFSource (const XMLNode&); SMFSource (Session& session, const XMLNode&);
virtual ~SMFSource (); virtual ~SMFSource ();

View file

@ -31,11 +31,11 @@ class SndFileSource : public AudioFileSource {
public: public:
/* constructor to be called for existing external-to-session files */ /* 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 */ /* 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| Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::Removable| AudioFileSource::Removable|
AudioFileSource::RemovableIfEmpty| AudioFileSource::RemovableIfEmpty|
@ -43,7 +43,7 @@ class SndFileSource : public AudioFileSource {
/* constructor to be called for existing in-session files */ /* constructor to be called for existing in-session files */
SndFileSource (const XMLNode&); SndFileSource (Session&, const XMLNode&);
~SndFileSource (); ~SndFileSource ();

View file

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

View file

@ -13,14 +13,17 @@ class XMLNode;
namespace ARDOUR { namespace ARDOUR {
class Session;
class SourceFactory { class SourceFactory {
public: public:
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated; 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); // MIDI sources will have to be hacked in here somehow
static boost::shared_ptr<Source> createWritable (DataType type, std::string name, bool destructive, jack_nframes_t rate, bool announce = true); 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); XMLNode& get_state (void);
int set_state (const XMLNode&); int set_state (const XMLNode&);
PBD::ID id() { return _id; }
void dump (std::ostream&) const; void dump (std::ostream&) const;
void clear (); void clear ();
@ -320,8 +319,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
void save_state (std::string why); void save_state (std::string why);
PBD::ID _id;
}; };
}; /* namespace ARDOUR */ }; /* namespace ARDOUR */

View file

@ -1590,7 +1590,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
string region_name; string region_name;
_session.region_name (region_name, channels[0].write_source->name(), false); _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 { try {
boost::shared_ptr<Region> rx (RegionFactory::create (srcs, buffer_position, (*ci)->frames, region_name)); 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 (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->mark_for_remove ();
chan.write_source.reset (); chan.write_source.reset ();
} else { } else {
@ -2185,7 +2185,8 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
} }
try { 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) { 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 bool
AudioEngine::get_sync_offset (jack_nframes_t& offset) const AudioEngine::get_sync_offset (jack_nframes_t& offset) const
{ {
#ifdef HAVE_JACK_VIDEO_SUPPORT
jack_position_t pos; jack_position_t pos;
(void) jack_transport_query (_jack, &pos); (void) jack_transport_query (_jack, &pos);
@ -176,6 +179,8 @@ AudioEngine::get_sync_offset (jack_nframes_t& offset) const
return true; return true;
} }
#endif
return false; 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_organization_code[4] = "LAS";
char AudioFileSource::bwf_serial_number[13] = "000000000000"; char AudioFileSource::bwf_serial_number[13] = "000000000000";
AudioFileSource::AudioFileSource (string idstr, Flag flags) AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
: AudioSource (idstr), _flags (flags) : AudioSource (s, idstr), _flags (flags)
{ {
/* constructor used for existing external to session files. file must exist already */ /* 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) AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
: AudioSource (path), _flags (flags) : AudioSource (s, path), _flags (flags)
{ {
/* constructor used for new internal-to-session files. file cannot exist */ /* 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) AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
: AudioSource (node), _flags (Flag (Writable|CanRename)) : AudioSource (s, node), _flags (Flag (Writable|CanRename))
{ {
/* constructor used for existing internal-to-session files. file must exist */ /* constructor used for existing internal-to-session files. file must exist */
@ -101,6 +101,7 @@ AudioFileSource::AudioFileSource (const XMLNode& node)
AudioFileSource::~AudioFileSource () AudioFileSource::~AudioFileSource ()
{ {
if (removable()) { if (removable()) {
cerr << "Removing file " << _path << " because its removable\n";
unlink (_path.c_str()); unlink (_path.c_str());
unlink (peakpath.c_str()); unlink (peakpath.c_str());
} }
@ -109,7 +110,7 @@ AudioFileSource::~AudioFileSource ()
bool bool
AudioFileSource::removable () const AudioFileSource::removable () const
{ {
return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_path))); return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
} }
int int
@ -135,7 +136,7 @@ AudioFileSource::init (string pathstr, bool must_exist)
string string
AudioFileSource::peak_path (string audio_path) 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 string
@ -527,7 +528,7 @@ void
AudioFileSource::set_allow_remove_if_empty (bool yn) AudioFileSource::set_allow_remove_if_empty (bool yn)
{ {
if (writable()) { if (writable()) {
allow_remove_if_empty = yn; _flags = Flag (_flags | RemovableIfEmpty);
} }
} }
@ -561,11 +562,12 @@ AudioFileSource::set_name (string newname, bool destructive)
} }
bool bool
AudioFileSource::is_empty (string path) AudioFileSource::is_empty (Session& s, string path)
{ {
bool ret = false; bool ret = false;
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ( 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) { if (afs) {
ret = (afs->length() == 0); ret = (afs->length() == 0);

View file

@ -51,7 +51,7 @@ AudioFilter::make_new_sources (boost::shared_ptr<AudioRegion> region, SourceList
try { try {
nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> ( 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) { catch (failed_constructor& err) {

View file

@ -38,7 +38,7 @@
#include <ardour/dB.h> #include <ardour/dB.h>
#include <ardour/playlist.h> #include <ardour/playlist.h>
#include <ardour/audiofilter.h> #include <ardour/audiofilter.h>
#include <ardour/audiosource.h> #include <ardour/audiofilesource.h>
#include "i18n.h" #include "i18n.h"
#include <locale.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), _fade_out (0.0, 2.0, 1.0, false),
_envelope (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; _scale_amplitude = 1.0;
set_default_fades (); 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) , _fade_out (0.0, 2.0, 1.0, false)
, _envelope (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; _scale_amplitude = 1.0;
set_default_fades (); 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) , _fade_out (0.0, 2.0, 1.0, false)
, _envelope (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 (); set_default_fades ();
if (set_state (node)) { if (set_state (node)) {
@ -1165,6 +1180,12 @@ AudioRegion::speed_mismatch (float sr) const
return fsr != sr; return fsr != sr;
} }
void
AudioRegion::source_offset_changed ()
{
set_position (source()->natural_position() + start(), this);
}
boost::shared_ptr<AudioSource> boost::shared_ptr<AudioSource>
AudioRegion::audio_source (uint32_t n) const 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_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false; bool AudioSource::_build_peakfiles = false;
AudioSource::AudioSource (string name) AudioSource::AudioSource (Session& s, string name)
: Source (name, DataType::AUDIO) : Source (s, name, DataType::AUDIO)
{ {
if (pending_peak_sources_lock == 0) { if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex; pending_peak_sources_lock = new Glib::Mutex;
@ -63,8 +63,8 @@ AudioSource::AudioSource (string name)
_write_data_count = 0; _write_data_count = 0;
} }
AudioSource::AudioSource (const XMLNode& node) AudioSource::AudioSource (Session& s, const XMLNode& node)
: Source (node) : Source (s, node)
{ {
if (pending_peak_sources_lock == 0) { if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex; pending_peak_sources_lock = new Glib::Mutex;

View file

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

View file

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

View file

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

View file

@ -140,7 +140,7 @@ Session::import_audiofile (import_status& status)
try { try {
newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> ( 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) { catch (failed_constructor& err) {

View file

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

View file

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

View file

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

View file

@ -1090,7 +1090,7 @@ Panner::save () const
ofstream out (automation_path.c_str()); ofstream out (automation_path.c_str());
if (!out) { 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; << endmsg;
return -1; 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)); free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
string path = string_compose("%1/.%2", envvar, domain); 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; warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false; return false;
} }
path += "/rdf"; 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; warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false; return false;
} }

View file

@ -277,17 +277,17 @@ Route::process_output_buffers (BufferSet& bufs,
-------------------------------------------------------------------------------------------------- */ -------------------------------------------------------------------------------------------------- */
if (declick > 0) { 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; _pending_declick = 0;
} else if (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; _pending_declick = 0;
} else { } else {
/* no global declick */ /* no global declick */
if (solo_gain != dsg) { if (solo_gain != dsg) {
Amp::run (bufs, nframes, solo_gain, dsg, _phase_invert); Amp::run (bufs, nframes, solo_gain, dsg, false);
solo_gain = dsg; solo_gain = dsg;
} }
} }
@ -302,7 +302,7 @@ Route::process_output_buffers (BufferSet& bufs,
} }
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) { 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_gain = dmg;
mute_declick_applied = true; 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) { 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_gain = dmg;
mute_declick_applied = true; 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) { 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_gain = dmg;
mute_declick_applied = true; 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) { 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_gain = dmg;
mute_declick_applied = true; mute_declick_applied = true;
} }

View file

@ -87,10 +87,11 @@ using boost::shared_ptr;
const char* Session::_template_suffix = X_(".template"); const char* Session::_template_suffix = X_(".template");
const char* Session::_statefile_suffix = X_(".ardour"); const char* Session::_statefile_suffix = X_(".ardour");
const char* Session::_pending_suffix = X_(".pending"); const char* Session::_pending_suffix = X_(".pending");
const char* Session::sound_dir_name = X_("sounds"); const char* Session::old_sound_dir_name = X_("sounds");
const char* Session::tape_dir_name = X_("tapes"); const char* Session::sound_dir_name = X_("audiofiles");
const char* Session::peak_dir_name = X_("peaks"); const char* Session::peak_dir_name = X_("peaks");
const char* Session::dead_sound_dir_name = X_("dead_sounds"); 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::compute_peak_t Session::compute_peak = 0;
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 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 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; string res;
res = Glib::path_get_dirname (audio_path); res = peak_dir ();
res = Glib::path_get_dirname (res);
res += '/';
res += peak_dir_name;
res += '/';
res += PBD::basename_nosuffix (audio_path); res += PBD::basename_nosuffix (audio_path);
res += ".peak"; res += ".peak";
@ -2992,11 +2987,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
spath = (*i).path; spath = (*i).path;
if (destructive) { spath += sound_dir (false);
spath += tape_dir_name;
} else {
spath += sound_dir_name;
}
if (destructive) { if (destructive) {
if (nchan < 2) { 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++; existing++;
} }
} }
if (existing == 0) { if (existing == 0) {
@ -3053,11 +3045,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
string foo = buf; 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 ('/'); 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) 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); 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 // FIXME: _terrible_ code duplication
@ -3260,7 +3249,7 @@ Session::create_midi_source_for_session (MidiDiskstream& ds)
{ {
string spath = midi_path_from_name (ds.name()); 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 void
Session::remove_empty_sounds () Session::remove_empty_sounds ()
{ {
PathScanner scanner; PathScanner scanner;
string dir;
dir = sound_dir (); vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64)$", false, true);
vector<string *>* possible_audiofiles = scanner (dir, "\\.wav$", false, true); Glib::Mutex::Lock lm (source_lock);
regex_t compiled_tape_track_pattern;
int err;
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) { for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
if (AudioFileSource::is_empty (*(*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()); unlink ((*i)->c_str());
@ -3914,7 +3921,8 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
} }
try { 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) { catch (failed_constructor& err) {
@ -3931,7 +3939,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
to_do = len; to_do = len;
/* create a set of reasonably-sized buffers */ /* create a set of reasonably-sized buffers */
buffers.ensure_buffers(nchans, chunk_size); buffers.ensure_buffers(nchans, chunk_size);
buffers.set_count(nchans); buffers.set_count(nchans);
while (to_do && !itt.cancel) { while (to_do && !itt.cancel) {

View file

@ -309,7 +309,6 @@ Session::second_stage_init (bool new_session)
if (!new_session) { if (!new_session) {
if (load_state (_current_snapshot_name)) { if (load_state (_current_snapshot_name)) {
cerr << "load state failed\n";
return -1; return -1;
} }
remove_empty_sounds (); remove_empty_sounds ();
@ -371,7 +370,6 @@ Session::second_stage_init (bool new_session)
_end_location_is_free = false; _end_location_is_free = false;
} }
restore_history(_current_snapshot_name);
return 0; return 0;
} }
@ -436,16 +434,7 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') { if (fspath[fspath.length()-1] != '/') {
fspath += '/'; fspath += '/';
} }
fspath += sound_dir_name; fspath += sound_dir (false);
fspath += ':';
/* tape dir */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
AudioFileSource::set_search_path (fspath); AudioFileSource::set_search_path (fspath);
SMFSource::set_search_path (fspath); // FIXME: should be different SMFSource::set_search_path (fspath); // FIXME: should be different
@ -467,16 +456,7 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') { if (fspath[fspath.length()-1] != '/') {
fspath += '/'; fspath += '/';
} }
fspath += sound_dir_name; fspath += sound_dir (false);
fspath += ':';
/* add tape dir to file search path */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
fspath += ':'; fspath += ':';
remaining = remaining.substr (colon+1); remaining = remaining.substr (colon+1);
@ -492,15 +472,9 @@ Session::setup_raid_path (string path)
if (fspath[fspath.length()-1] != '/') { if (fspath[fspath.length()-1] != '/') {
fspath += '/'; fspath += '/';
} }
fspath += sound_dir_name; fspath += sound_dir (false);
fspath += ':'; fspath += ':';
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
session_dirs.push_back (sp); session_dirs.push_back (sp);
} }
@ -519,61 +493,40 @@ Session::create (bool& new_session, string* mix_template, jack_nframes_t initial
{ {
string dir; string dir;
if (mkdir (_path.c_str(), 0755) < 0) { new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
if (errno == EEXIST) {
new_session = false; if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
} else {
error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg; error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
return -1; return -1;
} }
} else {
new_session = true;
}
dir = peak_dir (); dir = peak_dir ();
if (mkdir (dir.c_str(), 0755) < 0) { if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1; return -1;
} }
}
dir = sound_dir (); dir = sound_dir ();
if (mkdir (dir.c_str(), 0755) < 0) { if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1; 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;
}
}
dir = dead_sound_dir (); dir = dead_sound_dir ();
if (mkdir (dir.c_str(), 0755) < 0) { if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1; return -1;
} }
}
dir = automation_dir (); dir = automation_dir ();
if (mkdir (dir.c_str(), 0755) < 0) { if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
if (errno != EEXIST) {
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1; return -1;
} }
}
/* check new_session so we don't overwrite an existing one */ /* check new_session so we don't overwrite an existing one */
@ -725,6 +678,8 @@ Session::save_state (string snapshot_name, bool pending)
} }
cerr << "actually writing state\n";
if (!tree.write (xml_path)) { if (!tree.write (xml_path)) {
error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg; 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> boost::shared_ptr<Source>
Session::XMLSourceFactory (const XMLNode& node) Session::XMLSourceFactory (const XMLNode& node)
{ {
if (node.name() != "Source") { if (node.name() != "Source") {
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();
} }
try { try {
return SourceFactory::create (node); return SourceFactory::create (*this, node);
} }
catch (failed_constructor& err) { catch (failed_constructor& err) {
@ -2062,7 +2016,7 @@ Session::save_template (string template_name)
if ((dp = opendir (dir.c_str()))) { if ((dp = opendir (dir.c_str()))) {
closedir (dp); closedir (dp);
} else { } 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; error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1; return -1;
} }
@ -2142,12 +2096,10 @@ Session::ensure_sound_dir (string path, string& result)
/* Ensure that the parent directory exists */ /* Ensure that the parent directory exists */
if (mkdir (path.c_str(), 0775)) { if (g_mkdir_with_parents (path.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg; error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
return -1; return -1;
} }
}
/* Ensure that the sounds directory exists */ /* Ensure that the sounds directory exists */
@ -2155,34 +2107,28 @@ Session::ensure_sound_dir (string path, string& result)
result += '/'; result += '/';
result += sound_dir_name; result += sound_dir_name;
if (mkdir (result.c_str(), 0775)) { if (g_mkdir_with_parents (result.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg; error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
return -1; return -1;
} }
}
dead = path; dead = path;
dead += '/'; dead += '/';
dead += dead_sound_dir_name; dead += dead_sound_dir_name;
if (mkdir (dead.c_str(), 0775)) { if (g_mkdir_with_parents (dead.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg; error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
return -1; return -1;
} }
}
peak = path; peak = path;
peak += '/'; peak += '/';
peak += peak_dir_name; peak += peak_dir_name;
if (mkdir (peak.c_str(), 0775)) { if (g_mkdir_with_parents (peak.c_str(), 0775)) {
if (errno != EEXIST) {
error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg; error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
return -1; return -1;
} }
}
/* callers expect this to be terminated ... */ /* callers expect this to be terminated ... */
@ -2196,12 +2142,6 @@ Session::discover_best_sound_dir (bool destructive)
vector<space_and_path>::iterator i; vector<space_and_path>::iterator i;
string result; string result;
/* destructive files all go into the same place */
if (destructive) {
return tape_dir();
}
/* handle common case without system calls */ /* handle common case without system calls */
if (session_dirs.size() == 1) { if (session_dirs.size() == 1) {
@ -2418,20 +2358,37 @@ Session::dead_sound_dir () const
} }
string 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 += sound_dir_name;
res += '/'; res += '/';
return res;
}
string
Session::tape_dir () const
{
string res = _path;
res += tape_dir_name;
res += '/';
return res; return res;
} }
@ -3428,7 +3385,6 @@ Session::save_history (string snapshot_name)
string xml_path; string xml_path;
string bak_path; string bak_path;
tree.set_root (&history.get_state()); tree.set_root (&history.get_state());
if (snapshot_name.empty()) { if (snapshot_name.empty()) {
@ -3436,7 +3392,6 @@ Session::save_history (string snapshot_name)
} }
xml_path = _path + snapshot_name + ".history"; xml_path = _path + snapshot_name + ".history";
cerr << "Saving history to " << xml_path << endmsg;
bak_path = xml_path + ".bak"; bak_path = xml_path + ".bak";
@ -3447,6 +3402,8 @@ Session::save_history (string snapshot_name)
return -1; return -1;
} }
cerr << "actually writing history\n";
if (!tree.write (xml_path)) if (!tree.write (xml_path))
{ {
error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg; 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 void
Session::sync_time_vars () 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_hour = _current_frame_rate * 3600;
_frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second; _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); _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); pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
} }
#ifdef HAVE_JACK_VIDEO_SUPPORT
//poke audio video ratio so Ardour can track Video Sync //poke audio video ratio so Ardour can track Video Sync
pos->audio_frames_per_video_frame = frame_rate() / smpte_frames_per_second; pos->audio_frames_per_video_frame = frame_rate() / smpte_frames_per_second;
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio); pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
#endif
#if 0 #if 0
/* SMPTE info */ /* SMPTE info */

View file

@ -82,8 +82,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
} }
try { try {
sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> ( sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *this, path, false, frame_rate())));
SourceFactory::createWritable (DataType::AUDIO, path, false, frame_rate())));
} catch (failed_constructor& err) { } catch (failed_constructor& err) {
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg; 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; uint64_t SMFSource::header_position_offset;
*/ */
SMFSource::SMFSource (std::string path, Flag flags) SMFSource::SMFSource (Session& s, std::string path, Flag flags)
: MidiSource (region_name_from_path(path)) : MidiSource (s, region_name_from_path(path))
, _channel(0) , _channel(0)
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now , _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
, _allow_remove_if_empty(true) , _allow_remove_if_empty(true)
@ -72,8 +72,8 @@ SMFSource::SMFSource (std::string path, Flag flags)
assert(_name.find("/") == string::npos); assert(_name.find("/") == string::npos);
} }
SMFSource::SMFSource (const XMLNode& node) SMFSource::SMFSource (Session& s, const XMLNode& node)
: MidiSource (node) : MidiSource (s, node)
, _channel(0) , _channel(0)
, _flags (Flag (Writable|CanRename)) , _flags (Flag (Writable|CanRename))
, _allow_remove_if_empty(true) , _allow_remove_if_empty(true)

View file

@ -34,8 +34,8 @@ using namespace std;
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
SndFileSource::SndFileSource (const XMLNode& node) SndFileSource::SndFileSource (Session& s, const XMLNode& node)
: AudioFileSource (node) : AudioFileSource (s, node)
{ {
init (_name); 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 */ /* 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); 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) SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
: AudioFileSource(idstr, flags, sfmt, hf) : AudioFileSource (s, idstr, flags, sfmt, hf)
{ {
int fmt = 0; int fmt = 0;
@ -226,7 +226,6 @@ SndFileSource::open ()
_length = _info.frames; _length = _info.frames;
_broadcast_info = new SF_BROADCAST_INFO; _broadcast_info = new SF_BROADCAST_INFO;
memset (_broadcast_info, 0, sizeof (*_broadcast_info)); memset (_broadcast_info, 0, sizeof (*_broadcast_info));
@ -507,6 +506,9 @@ SndFileSource::set_header_timeline_position ()
delete _broadcast_info; delete _broadcast_info;
_broadcast_info = 0; _broadcast_info = 0;
} }
} }
jack_nframes_t jack_nframes_t

View file

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

View file

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

View file

@ -919,6 +919,33 @@ jack_nframes_t
TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num) 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::iterator i;
TempoMap::BBTPointList *more_zoomed_bbt_points; TempoMap::BBTPointList *more_zoomed_bbt_points;
jack_nframes_t frame_one_beats_worth; 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; delete more_zoomed_bbt_points;
return fr ; return fr ;
*/
} }
jack_nframes_t 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; 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; in[i] = in[i-1] + step;
} }

View file

@ -174,7 +174,7 @@ VSTPlugin::get_state()
if (stat (path.c_str(), &sbuf)) { if (stat (path.c_str(), &sbuf)) {
if (errno == ENOENT) { 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"), error << string_compose (_("cannot create VST chunk directory: %1"),
strerror (errno)) strerror (errno))
<< endmsg; << endmsg;

View file

@ -48,6 +48,8 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
uint32_t cnt = selection->size(); uint32_t cnt = selection->size();
uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers); uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
cerr << "lets plan to serialize " << cnt << " from selection\n";
char* buf = new char[sz]; char* buf = new char[sz];
SerializedObjectPointers* sr = new (buf) SerializedObjectPointers; SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
@ -59,10 +61,12 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
cnt = 0; cnt = 0;
for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) { 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)); TreeModel::Row row = *(model->get_iter (*x));
row.get_value (data_column, sr->ptr[cnt]); row.get_value (data_column, sr->ptr[cnt]);
} }
cerr << "returning an SR with size = " << sr->size << endl;
return sr; 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()); SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
selection_data.set (8, (guchar*)sr, sr->size); 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); virtual void add_instant_xml (XMLNode&, const std::string& dir);
XMLNode *instant_xml (const std::string& str, 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: protected:
XMLNode *_extra_xml; XMLNode *_extra_xml;