Merged with trunk R920.
git-svn-id: svn://localhost/ardour2/branches/midi@921 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
c7307c09b8
commit
7bd41538d9
11
SConstruct
11
SConstruct
|
@ -468,17 +468,6 @@ if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0:
|
|||
|
||||
libraries['boost'] = conf.Finish ()
|
||||
|
||||
conf = env.Configure ()
|
||||
|
||||
# jack_port_ensure_monitor available
|
||||
|
||||
if conf.CheckFunc('jack_port_ensure_monitor'):
|
||||
env.Append(CCFLAGS='-DWITH_JACK_PORT_ENSURE_MONITOR')
|
||||
else:
|
||||
print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
|
||||
|
||||
env = conf.Finish()
|
||||
|
||||
#
|
||||
# Check for liblo
|
||||
|
||||
|
|
|
@ -73,13 +73,13 @@ ActionManager::init ()
|
|||
ui_manager->add_ui_from_file (ui_file);
|
||||
loaded = true;
|
||||
} catch (Glib::MarkupError& err) {
|
||||
error << "badly formatted UI definition file" << endmsg;
|
||||
error << _("badly formatted UI definition file") << endmsg;
|
||||
} catch (...) {
|
||||
error << "Ardour menu definition file not found" << endmsg;
|
||||
error << _("Ardour menu definition file not found") << endmsg;
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
error << "ardour will not work without a valid ardour.menus file" << endmsg;
|
||||
error << _("ardour will not work without a valid ardour.menus file") << endmsg;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ ActionManager::uncheck_toggleaction (const char * name)
|
|||
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
|
||||
tact->set_active (false);
|
||||
} else {
|
||||
error << "Unknown action name: " << name << endmsg;
|
||||
error << string_compose (_("Unknown action name: %1"), name) << endmsg;
|
||||
}
|
||||
|
||||
delete [] group_name;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
source `dirname "$0"`/ardev_common.sh
|
||||
exec gtk2_ardour/ardour.bin --novst "$*"
|
||||
exec gtk2_ardour/ardour.bin --novst $*
|
||||
|
|
|
@ -214,6 +214,30 @@
|
|||
<menuitem action='FileHeaderFormatCAF'/>
|
||||
</menu>
|
||||
</menu>
|
||||
<menu action='SMPTE'>
|
||||
<menuitem action='Smpte23976'/>
|
||||
<menuitem action='Smpte24'/>
|
||||
<menuitem action='Smpte24976'/>
|
||||
<menuitem action='Smpte25'/>
|
||||
<menuitem action='Smpte2997drop'/>
|
||||
<menuitem action='Smpte2997'/>
|
||||
<menuitem action='Smpte30drop'/>
|
||||
<menuitem action='Smpte30'/>
|
||||
<menuitem action='Smpte5994'/>
|
||||
<menuitem action='Smpte60'/>
|
||||
</menu>
|
||||
<menu action='Pullup'>
|
||||
<menuitem action='PullupPlus4Plus1'/>
|
||||
<menuitem action='PullupPlus4'/>
|
||||
<menuitem action='PullupPlus4Minus1'/>
|
||||
<menuitem action='PullupPlus1'/>
|
||||
<menuitem action='PullupNone'/>
|
||||
<menuitem action='PullupMinus1'/>
|
||||
<menuitem action='PullupMinus4Plus1'/>
|
||||
<menuitem action='PullupMinus4'/>
|
||||
<menuitem action='PullupMinus4Minus1'/>
|
||||
</menu>
|
||||
<separator/>
|
||||
<menu action='Autoconnect'>
|
||||
<menuitem action='AutoConnectNewTrackInputsToHardware'/>
|
||||
<separator/>
|
||||
|
|
|
@ -1651,6 +1651,9 @@ ARDOUR_UI::save_template ()
|
|||
void
|
||||
ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
|
||||
{
|
||||
string session_name;
|
||||
string session_path;
|
||||
|
||||
int response = Gtk::RESPONSE_NONE;
|
||||
|
||||
new_session_dialog->set_modal(true);
|
||||
|
@ -1672,14 +1675,28 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
|
|||
new_session_dialog->reset();
|
||||
|
||||
} else if (response == Gtk::RESPONSE_YES) {
|
||||
|
||||
/* YES == OPEN, but there's no enum for that */
|
||||
|
||||
std::string session_name = new_session_dialog->session_name();
|
||||
std::string session_path = new_session_dialog->session_folder();
|
||||
load_session (session_path, session_name);
|
||||
session_name = new_session_dialog->session_name();
|
||||
|
||||
if (session_name.empty()) {
|
||||
response = Gtk::RESPONSE_NONE;
|
||||
cerr << "session name is empty\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session_name[0] == '/' ||
|
||||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
|
||||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
|
||||
load_session (Glib::path_get_dirname (session_name), session_name);
|
||||
} else {
|
||||
session_path = new_session_dialog->session_folder();
|
||||
load_session (session_path, session_name);
|
||||
}
|
||||
|
||||
} else if (response == Gtk::RESPONSE_OK) {
|
||||
|
||||
if (new_session_dialog->get_current_page() == 1) {
|
||||
|
||||
/* XXX this is a bit of a hack..
|
||||
|
@ -1687,93 +1704,121 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
|
|||
if we're on page 1 (the load page)
|
||||
Unfortunately i can't see how atm..
|
||||
*/
|
||||
|
||||
std::string session_name = new_session_dialog->session_name();
|
||||
std::string session_path = new_session_dialog->session_folder();
|
||||
load_session (session_path, session_name);
|
||||
|
||||
|
||||
if (session_name.empty()) {
|
||||
response = Gtk::RESPONSE_NONE;
|
||||
cerr << "session name is empty 2\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session_name[0] == '/' ||
|
||||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
|
||||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
|
||||
load_session (Glib::path_get_dirname (session_name), session_name);
|
||||
} else {
|
||||
session_path = new_session_dialog->session_folder();
|
||||
load_session (session_path, session_name);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
_session_is_new = true;
|
||||
|
||||
std::string session_name = new_session_dialog->session_name();
|
||||
std::string session_path = new_session_dialog->session_folder();
|
||||
session_name = new_session_dialog->session_name();
|
||||
|
||||
if (session_name.empty()) {
|
||||
response = Gtk::RESPONSE_NONE;
|
||||
cerr << "session name is empty 3\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session_name[0] == '/' ||
|
||||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
|
||||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
|
||||
|
||||
session_path = Glib::path_get_dirname (session_name);
|
||||
session_name = Glib::path_get_basename (session_name);
|
||||
|
||||
} else {
|
||||
|
||||
std::string session_path = new_session_dialog->session_folder();
|
||||
|
||||
}
|
||||
|
||||
//XXX This is needed because session constructor wants a
|
||||
//non-existant path. hopefully this will be fixed at some point.
|
||||
|
||||
session_path = Glib::build_filename(session_path, session_name);
|
||||
|
||||
|
||||
session_path = Glib::build_filename (session_path, session_name);
|
||||
|
||||
std::string template_name = new_session_dialog->session_template_name();
|
||||
|
||||
|
||||
if (new_session_dialog->use_session_template()) {
|
||||
|
||||
load_session (session_path, session_name, &template_name);
|
||||
|
||||
load_session (session_path, session_name, &template_name);
|
||||
|
||||
} else {
|
||||
|
||||
uint32_t cchns;
|
||||
|
||||
uint32_t cchns;
|
||||
uint32_t mchns;
|
||||
Session::AutoConnectOption iconnect;
|
||||
Session::AutoConnectOption oconnect;
|
||||
|
||||
|
||||
if (new_session_dialog->create_control_bus()) {
|
||||
cchns = (uint32_t) new_session_dialog->control_channel_count();
|
||||
cchns = (uint32_t) new_session_dialog->control_channel_count();
|
||||
} else {
|
||||
cchns = 0;
|
||||
cchns = 0;
|
||||
}
|
||||
|
||||
|
||||
if (new_session_dialog->create_master_bus()) {
|
||||
mchns = (uint32_t) new_session_dialog->master_channel_count();
|
||||
mchns = (uint32_t) new_session_dialog->master_channel_count();
|
||||
} else {
|
||||
mchns = 0;
|
||||
mchns = 0;
|
||||
}
|
||||
|
||||
|
||||
if (new_session_dialog->connect_inputs()) {
|
||||
iconnect = Session::AutoConnectPhysical;
|
||||
iconnect = Session::AutoConnectPhysical;
|
||||
} else {
|
||||
iconnect = Session::AutoConnectOption (0);
|
||||
iconnect = Session::AutoConnectOption (0);
|
||||
}
|
||||
|
||||
|
||||
/// @todo some minor tweaks.
|
||||
|
||||
|
||||
if (new_session_dialog->connect_outs_to_master()) {
|
||||
oconnect = Session::AutoConnectMaster;
|
||||
oconnect = Session::AutoConnectMaster;
|
||||
} else if (new_session_dialog->connect_outs_to_physical()) {
|
||||
oconnect = Session::AutoConnectPhysical;
|
||||
oconnect = Session::AutoConnectPhysical;
|
||||
} else {
|
||||
oconnect = Session::AutoConnectOption (0);
|
||||
oconnect = Session::AutoConnectOption (0);
|
||||
}
|
||||
|
||||
|
||||
uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
|
||||
uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
|
||||
|
||||
|
||||
build_session (session_path,
|
||||
session_name,
|
||||
cchns,
|
||||
mchns,
|
||||
iconnect,
|
||||
oconnect,
|
||||
nphysin,
|
||||
nphysout,
|
||||
engine->frame_rate() * 60 * 5);
|
||||
session_name,
|
||||
cchns,
|
||||
mchns,
|
||||
iconnect,
|
||||
oconnect,
|
||||
nphysin,
|
||||
nphysout,
|
||||
engine->frame_rate() * 60 * 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (response == Gtk::RESPONSE_NONE);
|
||||
|
||||
show();
|
||||
new_session_dialog->get_window()->set_cursor();
|
||||
|
||||
new_session_dialog->hide();
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::close_session()
|
||||
{
|
||||
unload_session();
|
||||
new_session ();
|
||||
unload_session();
|
||||
new_session ();
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1873,6 +1918,11 @@ ARDOUR_UI::show ()
|
|||
{
|
||||
if (editor) {
|
||||
editor->show_window ();
|
||||
|
||||
if (!shown_flag) {
|
||||
editor->present ();
|
||||
}
|
||||
|
||||
shown_flag = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,10 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
|
|||
{
|
||||
editor->connect_to_session (s);
|
||||
mixer->connect_to_session (s);
|
||||
|
||||
/* its safe to do this now */
|
||||
|
||||
s->restore_history (s->snap_name());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -131,10 +131,6 @@ ARDOUR_UI::connect_to_session (Session *s)
|
|||
start_clocking ();
|
||||
start_blinking ();
|
||||
|
||||
if (editor) {
|
||||
editor->present();
|
||||
}
|
||||
|
||||
transport_stopped ();
|
||||
|
||||
second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_second), 1000);
|
||||
|
|
|
@ -463,6 +463,7 @@ ARDOUR_UI::setup_session_options ()
|
|||
session_control_changed (Session::AutoReturn);
|
||||
session_control_changed (Session::AutoInput);
|
||||
session_control_changed (Session::Clicking);
|
||||
session_control_changed (Session::SmpteMode);
|
||||
|
||||
session->ControlChanged.connect (mem_fun (*this, &ARDOUR_UI::queue_session_control_changed));
|
||||
}
|
||||
|
@ -555,7 +556,6 @@ ARDOUR_UI::session_control_changed (Session::ControlType t)
|
|||
case Session::CrossfadingModel:
|
||||
break;
|
||||
|
||||
|
||||
case Session::AutoPlay:
|
||||
map_some_session_state ("Transport", "ToggleAutoPlay", &Session::get_auto_play);
|
||||
break;
|
||||
|
|
|
@ -68,6 +68,7 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
|
|||
_amplitude_above_axis = 1.0;
|
||||
|
||||
use_rec_regions = tv.editor.show_waveforms_recording ();
|
||||
|
||||
}
|
||||
|
||||
AudioStreamView::~AudioStreamView ()
|
||||
|
@ -215,9 +216,7 @@ AudioStreamView::playlist_modified ()
|
|||
|
||||
StreamView::playlist_modified();
|
||||
|
||||
/* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked
|
||||
correctly.
|
||||
*/
|
||||
/* make sure xfades are on top and all the regionviews are stacked correctly. */
|
||||
|
||||
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
|
||||
(*i)->get_canvas_group()->raise_to_top();
|
||||
|
@ -419,10 +418,11 @@ AudioStreamView::setup_rec_box ()
|
|||
|
||||
boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion>
|
||||
(RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false)));
|
||||
assert(region);
|
||||
region->set_position (_trackview.session().transport_frame(), this);
|
||||
rec_regions.push_back (region);
|
||||
/* catch it if it goes away */
|
||||
region->GoingAway.connect (bind (mem_fun (*this, &AudioStreamView::remove_rec_region), region));
|
||||
|
||||
// rec regions are destroyed in setup_rec_box
|
||||
|
||||
/* we add the region later */
|
||||
}
|
||||
|
@ -504,6 +504,14 @@ AudioStreamView::setup_rec_box ()
|
|||
|
||||
/* remove temp regions */
|
||||
|
||||
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) {
|
||||
list<boost::shared_ptr<Region> >::iterator tmp;
|
||||
tmp = iter;
|
||||
++tmp;
|
||||
(*iter)->drop_references ();
|
||||
iter = tmp;
|
||||
}
|
||||
|
||||
rec_regions.clear();
|
||||
|
||||
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";
|
||||
|
@ -567,9 +575,10 @@ AudioStreamView::update_rec_regions ()
|
|||
continue;
|
||||
}
|
||||
|
||||
// FIXME
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(*iter);
|
||||
assert(region);
|
||||
if (!region) {
|
||||
continue;
|
||||
}
|
||||
|
||||
jack_nframes_t origlen = region->length();
|
||||
|
||||
|
|
|
@ -163,9 +163,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
|||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
protected:
|
||||
PBD::ID _id;
|
||||
|
||||
string _name;
|
||||
guint32 _height;
|
||||
uint32_t _line_color;
|
||||
|
|
|
@ -263,7 +263,7 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
|
|||
GnomeCanvasSimpleRect* simplerect;
|
||||
double x1, x2, y1, y2;
|
||||
double old_x1, old_x2, old_y1, old_y2;
|
||||
double a, b;
|
||||
double a, b, c, d;
|
||||
|
||||
old_x1 = item->x1;
|
||||
old_y1 = item->y1;
|
||||
|
@ -287,42 +287,24 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
|
|||
gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
|
||||
|
||||
/* now queue redraws for changed areas */
|
||||
|
||||
if (item->x1 != old_x1) {
|
||||
|
||||
/* left edge changed. redraw the area that altered */
|
||||
|
||||
a = MIN(item->x1, old_x1);
|
||||
b = MAX(item->x1, old_x1);
|
||||
gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
|
||||
}
|
||||
|
||||
if (item->x2 != old_x2) {
|
||||
|
||||
/* right edge changed. redraw the area that altered */
|
||||
|
||||
a = MIN(item->x2, old_x2);
|
||||
b = MAX(item->x2, old_x2);
|
||||
gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
|
||||
}
|
||||
|
||||
if (item->y1 != old_y1) {
|
||||
|
||||
/* top edge changed. redraw the area that altered */
|
||||
|
||||
a = MIN(item->y1, old_y1);
|
||||
b = MAX(item->y1, old_y1);
|
||||
gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
|
||||
}
|
||||
|
||||
if (item->y2 != old_y2) {
|
||||
|
||||
/* lower edge changed. redraw the area that altered */
|
||||
|
||||
a = MIN(item->y2, old_y2);
|
||||
b = MAX(item->y2, old_y2);
|
||||
gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
|
||||
}
|
||||
|
||||
a = MIN(a, item->x2);
|
||||
a = MIN(a, old_x2);
|
||||
b = MAX(b, item->x2);
|
||||
b = MAX(b, old_x2);
|
||||
|
||||
c = MIN(item->y1, old_y1);
|
||||
d = MAX(item->y1, old_y1);
|
||||
|
||||
c = MIN(c,item->y2);
|
||||
c = MIN(c, old_y2);
|
||||
d = MAX(d,item->y2);
|
||||
d = MAX(d, old_y2);
|
||||
|
||||
gnome_canvas_request_redraw (item->canvas, a, c, b + 0.5, d + 0.5);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -494,8 +476,8 @@ gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *c
|
|||
gnome_canvas_request_redraw (item->canvas,
|
||||
simplerect->bbox_ulx,
|
||||
simplerect->bbox_uly,
|
||||
simplerect->bbox_lrx+1,
|
||||
simplerect->bbox_lry+1);
|
||||
simplerect->bbox_lrx+0.5,
|
||||
simplerect->bbox_lry+0.5);
|
||||
simplerect->full_draw_on_update = FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ DISPLAYCONTROL(ShowMeasures)
|
|||
DISPLAYCONTROL(ShowWaveforms)
|
||||
DISPLAYCONTROL(ShowWaveformsRecording)
|
||||
|
||||
IMPORTMODE(ImportAsRegion)
|
||||
IMPORTMODE(ImportAsTrack)
|
||||
IMPORTMODE(ImportAsTapeTrack)
|
||||
IMPORTMODE(ImportToTrack)
|
||||
// if this is changed, remember to update the string table in sfdb_ui.cc
|
||||
IMPORTMODE(ImportAsRegion=0)
|
||||
IMPORTMODE(ImportToTrack=1)
|
||||
IMPORTMODE(ImportAsTrack=2)
|
||||
IMPORTMODE(ImportAsTapeTrack=3)
|
||||
|
|
|
@ -643,7 +643,7 @@ Editor::Editor (AudioEngine& eng)
|
|||
edit_pane.pack1 (edit_packer, true, true);
|
||||
edit_pane.pack2 (the_notebook, false, true);
|
||||
|
||||
edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
|
||||
edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
|
||||
|
||||
top_hbox.pack_start (toolbar_frame, true, true);
|
||||
|
||||
|
@ -700,6 +700,7 @@ Editor::Editor (AudioEngine& eng)
|
|||
ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false));
|
||||
ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true));
|
||||
ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
|
||||
|
||||
constructed = true;
|
||||
instant_save ();
|
||||
|
||||
|
@ -882,6 +883,9 @@ Editor::reposition_x_origin (jack_nframes_t frame)
|
|||
}
|
||||
|
||||
horizontal_adjustment.set_value (frame/frames_per_unit);
|
||||
} else {
|
||||
update_fixed_rulers();
|
||||
tempo_map_changed (Change (0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,20 +969,10 @@ void
|
|||
Editor::canvas_horizontally_scrolled ()
|
||||
{
|
||||
|
||||
Glib::signal_idle().connect (mem_fun(*this, &Editor::lazy_canvas_horizontally_scrolled));
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::lazy_canvas_horizontally_scrolled ()
|
||||
{
|
||||
|
||||
leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
|
||||
|
||||
leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
|
||||
update_fixed_rulers ();
|
||||
tempo_map_changed (Change (0));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -996,7 +990,6 @@ Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
|
|||
|
||||
set_frames_per_unit (nfpu);
|
||||
reposition_x_origin (frame);
|
||||
|
||||
repos_zoom_queued = false;
|
||||
|
||||
return FALSE;
|
||||
|
@ -1033,6 +1026,10 @@ Editor::session_control_changed (Session::ControlType t)
|
|||
update_layering_model ();
|
||||
break;
|
||||
|
||||
case Session::SmpteMode:
|
||||
update_smpte_mode ();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1179,6 +1176,9 @@ Editor::connect_to_session (Session *t)
|
|||
session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
|
||||
session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
|
||||
|
||||
session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_smpte_mode)));
|
||||
session_connections.push_back (session->PullupChanged.connect (mem_fun(*this, &Editor::update_video_pullup)));
|
||||
|
||||
session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
|
||||
|
||||
edit_groups_changed ();
|
||||
|
@ -1266,9 +1266,12 @@ Editor::connect_to_session (Session *t)
|
|||
}
|
||||
|
||||
/* xfade visibility state set from editor::set_state() */
|
||||
|
||||
update_crossfade_model ();
|
||||
update_layering_model ();
|
||||
|
||||
update_crossfade_model();
|
||||
update_layering_model();
|
||||
|
||||
update_smpte_mode();
|
||||
update_video_pullup();
|
||||
|
||||
handle_new_duration ();
|
||||
|
||||
|
@ -1292,7 +1295,7 @@ Editor::connect_to_session (Session *t)
|
|||
horizontal_adjustment.set_value (0);
|
||||
|
||||
restore_ruler_visibility ();
|
||||
tempo_map_changed (Change (0));
|
||||
//tempo_map_changed (Change (0));
|
||||
session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
|
||||
|
||||
edit_cursor->set_position (0);
|
||||
|
@ -1328,6 +1331,7 @@ Editor::connect_to_session (Session *t)
|
|||
}
|
||||
|
||||
/* register for undo history */
|
||||
|
||||
session->register_with_memento_command_factory(_id, this);
|
||||
}
|
||||
|
||||
|
@ -2110,6 +2114,9 @@ Editor::set_state (const XMLNode& node)
|
|||
int x, y, xoff, yoff;
|
||||
Gdk::Geometry g;
|
||||
|
||||
if ((prop = node.property ("id")) != 0) {
|
||||
_id = prop->value ();
|
||||
}
|
||||
|
||||
if ((geometry = find_named_node (node, "geometry")) == 0) {
|
||||
|
||||
|
@ -2241,6 +2248,9 @@ Editor::get_state ()
|
|||
XMLNode* node = new XMLNode ("Editor");
|
||||
char buf[32];
|
||||
|
||||
_id.print (buf);
|
||||
node->add_property ("id", buf);
|
||||
|
||||
if (is_realized()) {
|
||||
Glib::RefPtr<Gdk::Window> win = get_window();
|
||||
|
||||
|
@ -2250,7 +2260,7 @@ Editor::get_state ()
|
|||
win->get_size(width, height);
|
||||
|
||||
XMLNode* geometry = new XMLNode ("geometry");
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", width);
|
||||
geometry->add_property("x_size", string(buf));
|
||||
snprintf(buf, sizeof(buf), "%d", height);
|
||||
|
@ -4085,6 +4095,7 @@ Editor::restore_editing_space ()
|
|||
{
|
||||
mouse_mode_tearoff->set_visible (true);
|
||||
tools_tearoff->set_visible (true);
|
||||
|
||||
edit_pane.set_position (pre_maximal_pane_position);
|
||||
|
||||
unfullscreen();
|
||||
|
@ -4138,6 +4149,87 @@ Editor::on_key_press_event (GdkEventKey* ev)
|
|||
return key_press_focus_accelerator_handler (*this, ev);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::update_smpte_mode ()
|
||||
{
|
||||
ENSURE_GUI_THREAD(mem_fun(*this, &Editor::update_smpte_mode));
|
||||
|
||||
RefPtr<Action> act;
|
||||
|
||||
float frames = session->smpte_frames_per_second;
|
||||
bool drop = session->smpte_drop_frames;
|
||||
|
||||
if ((frames < 23.976 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte23976"));
|
||||
else if ((frames < 24 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte24"));
|
||||
else if ((frames < 24.976 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte24976"));
|
||||
else if ((frames < 25 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte25"));
|
||||
else if ((frames < 29.97 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997"));
|
||||
else if ((frames < 29.97 * 1.0005) && drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997drop"));
|
||||
else if ((frames < 30 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte30"));
|
||||
else if ((frames < 30 * 1.0005) && drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte30drop"));
|
||||
else if ((frames < 59.94 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte5994"));
|
||||
else if ((frames < 60 * 1.0005) && !drop)
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte60"));
|
||||
else
|
||||
cerr << "Unexpected SMPTE value (" << frames << (drop ? "drop" : "") << ") in update_smpte_mode. Menu is probably wrong\n" << endl;
|
||||
|
||||
|
||||
if (act) {
|
||||
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
|
||||
if (ract && !ract->get_active()) {
|
||||
ract->set_active (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::update_video_pullup ()
|
||||
{
|
||||
ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_video_pullup));
|
||||
|
||||
RefPtr<Action> act;
|
||||
|
||||
float pullup = session->video_pullup;
|
||||
|
||||
if ( pullup < (-4.1667 - 0.1) * 0.99) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Minus1"));
|
||||
} else if ( pullup < (-4.1667) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4"));
|
||||
} else if ( pullup < (-4.1667 + 0.1) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Plus1"));
|
||||
} else if ( pullup < (-0.1) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus1"));
|
||||
} else if (pullup > (4.1667 + 0.1) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Plus1"));
|
||||
} else if ( pullup > (4.1667) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4"));
|
||||
} else if ( pullup > (4.1667 - 0.1) * 0.99) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Minus1"));
|
||||
} else if ( pullup > (0.1) * 0.99 ) {
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus1"));
|
||||
} else
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupNone"));
|
||||
|
||||
|
||||
if (act) {
|
||||
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
|
||||
if (ract && !ract->get_active()) {
|
||||
ract->set_active (true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Editor::update_layering_model ()
|
||||
{
|
||||
|
@ -4163,7 +4255,6 @@ Editor::update_layering_model ()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Editor::update_crossfade_model ()
|
||||
{
|
||||
|
|
|
@ -143,8 +143,6 @@ class Editor : public PublicEditor
|
|||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode& );
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
|
||||
void set_mouse_mode (Editing::MouseMode, bool force=true);
|
||||
void step_mouse_mode (bool next);
|
||||
Editing::MouseMode current_mouse_mode () { return mouse_mode; }
|
||||
|
@ -231,6 +229,7 @@ class Editor : public PublicEditor
|
|||
|
||||
void set_show_measures (bool yn);
|
||||
bool show_measures () const { return _show_measures; }
|
||||
bool initial_ruler_update_required;
|
||||
|
||||
#ifdef FFT_ANALYSIS
|
||||
/* analysis window */
|
||||
|
@ -302,6 +301,14 @@ class Editor : public PublicEditor
|
|||
void set_meter_falloff (int);
|
||||
void set_meter_hold (int32_t);
|
||||
|
||||
/* SMPTE timecode & video sync */
|
||||
|
||||
void smpte_fps_chosen (ARDOUR::Session::SmpteFormat format);
|
||||
void video_pullup_chosen (ARDOUR::Session::PullupFormat pullup);
|
||||
|
||||
void update_smpte_mode();
|
||||
void update_video_pullup();
|
||||
|
||||
/* xfades */
|
||||
|
||||
void toggle_auto_xfade ();
|
||||
|
@ -311,8 +318,8 @@ class Editor : public PublicEditor
|
|||
void update_crossfade_model ();
|
||||
void set_crossfade_model (ARDOUR::CrossfadeModel);
|
||||
|
||||
/* layers */
|
||||
|
||||
/* layers */
|
||||
void set_layer_model (ARDOUR::Session::LayerModel);
|
||||
void update_layering_model ();
|
||||
|
||||
|
@ -349,8 +356,6 @@ class Editor : public PublicEditor
|
|||
ARDOUR::AudioEngine& engine;
|
||||
bool constructed;
|
||||
|
||||
PBD::ID _id;
|
||||
|
||||
PlaylistSelector* _playlist_selector;
|
||||
|
||||
void set_frames_per_unit (double);
|
||||
|
@ -683,7 +688,7 @@ class Editor : public PublicEditor
|
|||
|
||||
void tie_vertical_scrolling ();
|
||||
void canvas_horizontally_scrolled ();
|
||||
bool lazy_canvas_horizontally_scrolled ();
|
||||
|
||||
void reposition_and_zoom (jack_nframes_t sample, double fpu);
|
||||
gint deferred_reposition_and_zoom (jack_nframes_t sample, double fpu);
|
||||
void end_location_changed (ARDOUR::Location*);
|
||||
|
@ -1185,8 +1190,6 @@ class Editor : public PublicEditor
|
|||
bool _follow_playhead;
|
||||
bool _show_waveforms_recording;
|
||||
|
||||
void add_bbt_marks (ARDOUR::TempoMap::BBTPointList&);
|
||||
|
||||
ARDOUR::TempoMap::BBTPointList *current_bbt_points;
|
||||
|
||||
typedef vector<ArdourCanvas::SimpleLine*> TimeLineList;
|
||||
|
@ -1197,7 +1200,7 @@ class Editor : public PublicEditor
|
|||
ArdourCanvas::SimpleLine* get_time_line ();
|
||||
void hide_measures ();
|
||||
void draw_measures ();
|
||||
void draw_time_bars ();
|
||||
bool lazy_hide_and_draw_measures ();
|
||||
|
||||
void new_tempo_section ();
|
||||
|
||||
|
@ -1506,7 +1509,7 @@ class Editor : public PublicEditor
|
|||
jack_nframes_t autoscroll_distance;
|
||||
|
||||
static gint _autoscroll_canvas (void *);
|
||||
gint autoscroll_canvas ();
|
||||
bool autoscroll_canvas ();
|
||||
void start_canvas_autoscroll (int direction);
|
||||
void stop_canvas_autoscroll ();
|
||||
void maybe_autoscroll (GdkEvent*);
|
||||
|
|
|
@ -39,6 +39,8 @@ Editor::register_actions ()
|
|||
ActionManager::register_action (editor_actions, X_("Monitoring"), _("Monitoring"));
|
||||
ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect"));
|
||||
ActionManager::register_action (editor_actions, X_("Layering"), _("Layering"));
|
||||
ActionManager::register_action (editor_actions, X_("SMPTE"), _("SMPTE fps"));
|
||||
ActionManager::register_action (editor_actions, X_("Pullup"), _("Pullup / Pulldown"));
|
||||
ActionManager::register_action (editor_actions, X_("Metering"), _("Metering"));
|
||||
ActionManager::register_action (editor_actions, X_("MeteringFallOffRate"), _("Fall off rate"));
|
||||
ActionManager::register_action (editor_actions, X_("MeteringHoldTime"), _("Hold Time"));
|
||||
|
@ -393,6 +395,31 @@ Editor::register_actions ()
|
|||
ActionManager::register_radio_action (editor_actions, layer_model_group, X_("LayerMoveAddHigher"), _("Most Recently Moved/Added is Higher"), bind (mem_fun (*this, &Editor::set_layer_model), Session::MoveAddHigher));
|
||||
ActionManager::register_radio_action (editor_actions, layer_model_group, X_("LayerAddHigher"), _("Most Recently Added is Higher"), bind (mem_fun (*this, &Editor::set_layer_model), Session::AddHigher));
|
||||
|
||||
RadioAction::Group smpte_group;
|
||||
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte23976"), _("23.976"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_23976));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte24"), _("24"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_24));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte24976"), _("24.976"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_24976));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte25"), _("25"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_25));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte2997"), _("29.97"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_2997));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte2997drop"), _("29.97 drop"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_2997drop));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte30"), _("30"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_30));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte30drop"), _("30 drop"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_30drop));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte5994"), _("59.94"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_5994));
|
||||
ActionManager::register_radio_action (editor_actions, smpte_group, X_("Smpte60"), _("60"), bind (mem_fun (*this, &Editor::smpte_fps_chosen), Session::smpte_60));
|
||||
|
||||
RadioAction::Group pullup_group;
|
||||
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4Plus1"), _("+4.1667% + 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4Plus1));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4"), _("+4.1667%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus4Minus1"), _("+4.1667% - 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus4Minus1));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupPlus1"), _("+ 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Plus1));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupNone"), _("None"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_None));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus1"), _("- 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus1));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4Plus1"), _("-4.1667% + 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4Plus1));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4"), _("-4.1667%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4));
|
||||
ActionManager::register_radio_action (editor_actions, pullup_group, X_("PullupMinus4Minus1"), _("-4.1667% - 0.1%"), bind (mem_fun (*this, &Editor::video_pullup_chosen), Session::pullup_Minus4Minus1));
|
||||
|
||||
ActionManager::add_action_group (rl_actions);
|
||||
ActionManager::add_action_group (zoom_actions);
|
||||
ActionManager::add_action_group (mouse_mode_actions);
|
||||
|
@ -492,6 +519,150 @@ Editor::set_layer_model (Session::LayerModel model)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::smpte_fps_chosen (Session::SmpteFormat format)
|
||||
{
|
||||
/* this is driven by a toggle on a radio group, and so is invoked twice,
|
||||
once for the item that became inactive and once for the one that became
|
||||
active.
|
||||
*/
|
||||
|
||||
if (session) {
|
||||
|
||||
float fps = 10;
|
||||
bool drop = false;
|
||||
|
||||
RefPtr<Action> act;
|
||||
|
||||
switch (format) {
|
||||
case Session::smpte_23976: {
|
||||
fps=23.976;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte23976"));
|
||||
} break;
|
||||
case Session::smpte_24: {
|
||||
fps=24;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte24"));
|
||||
} break;
|
||||
case Session::smpte_24976: {
|
||||
fps=24.976;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte24976"));
|
||||
} break;
|
||||
case Session::smpte_25: {
|
||||
fps=25;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte25"));
|
||||
} break;
|
||||
case Session::smpte_2997: {
|
||||
fps=29.97;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997"));
|
||||
} break;
|
||||
case Session::smpte_2997drop: {
|
||||
fps=29.97;
|
||||
drop = true;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte2997drop"));
|
||||
} break;
|
||||
case Session::smpte_30: {
|
||||
fps=30;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte30"));
|
||||
} break;
|
||||
case Session::smpte_30drop: {
|
||||
fps=30;
|
||||
drop = true;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte30drop"));
|
||||
} break;
|
||||
case Session::smpte_5994: {
|
||||
fps=59.94;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte5994"));
|
||||
} break;
|
||||
case Session::smpte_60: {
|
||||
fps=60;
|
||||
drop = false;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("Smpte60"));
|
||||
} break;
|
||||
default:
|
||||
cerr << "Editor received unexpected smpte type" << endl;
|
||||
}
|
||||
|
||||
if (act) {
|
||||
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
|
||||
if (ract && ract->get_active()) {
|
||||
session->set_smpte_type (fps, drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::video_pullup_chosen (Session::PullupFormat pullup)
|
||||
{
|
||||
/* this is driven by a toggle on a radio group, and so is invoked twice,
|
||||
once for the item that became inactive and once for the one that became
|
||||
active.
|
||||
*/
|
||||
|
||||
if (session) {
|
||||
|
||||
RefPtr<Action> act;
|
||||
|
||||
float pull = 0.0;
|
||||
|
||||
switch (pullup) {
|
||||
case Session::pullup_Plus4Plus1:{
|
||||
pull = 4.1667 + 0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Plus1"));
|
||||
} break;
|
||||
case Session::pullup_Plus4:{
|
||||
pull = 4.1667;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4"));
|
||||
} break;
|
||||
case Session::pullup_Plus4Minus1:{
|
||||
pull = 4.1667 - 0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus4Minus1"));
|
||||
} break;
|
||||
case Session::pullup_Plus1:{
|
||||
pull = 0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupPlus1"));
|
||||
} break;
|
||||
case Session::pullup_None:{
|
||||
pull = 0.0;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupNone"));
|
||||
} break;
|
||||
case Session::pullup_Minus1:{
|
||||
pull = -0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus1"));
|
||||
} break;
|
||||
case Session::pullup_Minus4Plus1:{
|
||||
pull = -4.1667 + 0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Plus1"));
|
||||
} break;
|
||||
case Session::pullup_Minus4:{
|
||||
pull = -4.1667;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4"));
|
||||
} break;
|
||||
case Session::pullup_Minus4Minus1:{
|
||||
pull = -4.1667 - 0.1;
|
||||
act = ActionManager::get_action (X_("Editor"), X_("PullupMinus4Minus1"));
|
||||
} break;
|
||||
default:
|
||||
cerr << "Session received unexpected pullup type" << endl;
|
||||
}
|
||||
|
||||
if (act) {
|
||||
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
|
||||
if (ract && ract->get_active()) {
|
||||
session->set_video_pullup ( pull );
|
||||
}
|
||||
} else cerr << "Editor::video_pullup_chosen could not find action to match pullup." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Editor::set_crossfade_model (CrossfadeModel model)
|
||||
{
|
||||
|
|
|
@ -270,7 +270,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
|
|||
idspec += string_compose(":%1", n);
|
||||
|
||||
try {
|
||||
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
|
||||
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
|
||||
sources.push_back(source);
|
||||
}
|
||||
|
||||
|
|
|
@ -266,14 +266,15 @@ Editor::initialize_canvas ()
|
|||
|
||||
edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event);
|
||||
playhead_cursor = new Cursor (*this, "red", &Editor::canvas_playhead_cursor_event);
|
||||
|
||||
|
||||
initial_ruler_update_required = true;
|
||||
track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Editor::track_canvas_allocate (Gtk::Allocation alloc)
|
||||
{
|
||||
static bool first_time = true;
|
||||
|
||||
canvas_width = alloc.get_width();
|
||||
canvas_height = alloc.get_height();
|
||||
|
@ -318,14 +319,16 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
|
|||
transport_punchout_line->property_y2() = canvas_height;
|
||||
}
|
||||
|
||||
update_fixed_rulers ();
|
||||
|
||||
if (is_visible() && first_time) {
|
||||
if (is_visible() && initial_ruler_update_required) {
|
||||
/*
|
||||
this is really dumb, but signal_size_allocate() gets emitted intermittently
|
||||
depending on whether the canvas contents are visible or not.
|
||||
we only want to do this once
|
||||
*/
|
||||
update_fixed_rulers();
|
||||
tempo_map_changed (Change (0));
|
||||
first_time = false;
|
||||
} else {
|
||||
redisplay_tempo ();
|
||||
}
|
||||
initial_ruler_update_required = false;
|
||||
}
|
||||
|
||||
Resized (); /* EMIT_SIGNAL */
|
||||
}
|
||||
|
@ -414,6 +417,8 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
|
|||
const SelectionData& data,
|
||||
guint info, guint time)
|
||||
{
|
||||
cerr << "dropping, target = " << data.get_target() << endl;
|
||||
|
||||
if (data.get_target() == "regions") {
|
||||
drop_regions (context, x, y, data, info, time);
|
||||
} else {
|
||||
|
@ -528,7 +533,7 @@ Editor::maybe_autoscroll (GdkEvent* event)
|
|||
}
|
||||
|
||||
|
||||
if (autoscroll_direction != last_autoscroll_direction) {
|
||||
if ((autoscroll_direction != last_autoscroll_direction) || (leftmost_frame < frame < rightmost_frame)) {
|
||||
stop_canvas_autoscroll ();
|
||||
}
|
||||
|
||||
|
@ -542,14 +547,13 @@ Editor::maybe_autoscroll (GdkEvent* event)
|
|||
gint
|
||||
Editor::_autoscroll_canvas (void *arg)
|
||||
{
|
||||
return ((Editor *) arg)->autoscroll_canvas ();
|
||||
return ((Editor *) arg)->autoscroll_canvas ();
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
Editor::autoscroll_canvas ()
|
||||
{
|
||||
jack_nframes_t new_frame;
|
||||
bool keep_calling = true;
|
||||
jack_nframes_t limit = max_frames - current_page_frames();
|
||||
GdkEventMotion ev;
|
||||
jack_nframes_t target_frame;
|
||||
|
@ -570,10 +574,6 @@ Editor::autoscroll_canvas ()
|
|||
target_frame = drag_info.current_pointer_frame + autoscroll_distance;
|
||||
}
|
||||
|
||||
if (new_frame != leftmost_frame) {
|
||||
reposition_x_origin (new_frame);
|
||||
}
|
||||
|
||||
/* now fake a motion event to get the object that is being dragged to move too */
|
||||
|
||||
ev.type = GDK_MOTION_NOTIFY;
|
||||
|
@ -593,20 +593,26 @@ Editor::autoscroll_canvas ()
|
|||
|
||||
/* connect the timeout so that we get called repeatedly */
|
||||
|
||||
autoscroll_timeout_tag = g_timeout_add (20, _autoscroll_canvas, this);
|
||||
keep_calling = false;
|
||||
autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
|
||||
return false;
|
||||
|
||||
} else if (autoscroll_cnt == 50) { /* 0.5 seconds */
|
||||
}
|
||||
|
||||
if (new_frame != leftmost_frame) {
|
||||
reposition_x_origin (new_frame);
|
||||
}
|
||||
|
||||
if (autoscroll_cnt == 50) { /* 0.5 seconds */
|
||||
|
||||
/* after about a while, speed up a bit by changing the timeout interval */
|
||||
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/50.0f);
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/30.0f);
|
||||
|
||||
} else if (autoscroll_cnt == 75) { /* 1.0 seconds */
|
||||
} else if (autoscroll_cnt == 150) { /* 1.0 seconds */
|
||||
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/20.0f);
|
||||
|
||||
} else if (autoscroll_cnt == 100) { /* 1.5 seconds */
|
||||
} else if (autoscroll_cnt == 300) { /* 1.5 seconds */
|
||||
|
||||
/* after about another while, speed up by increasing the shift per callback */
|
||||
|
||||
|
@ -614,7 +620,7 @@ Editor::autoscroll_canvas ()
|
|||
|
||||
}
|
||||
|
||||
return keep_calling;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -631,7 +637,7 @@ Editor::start_canvas_autoscroll (int dir)
|
|||
autoscroll_cnt = 0;
|
||||
|
||||
/* do it right now, which will start the repeated callbacks */
|
||||
|
||||
|
||||
autoscroll_canvas ();
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
|
|||
|
||||
|
||||
try {
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path, AudioFileSource::Flag (0)));
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
@ -343,7 +343,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
|
|||
path = s;
|
||||
|
||||
try {
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path, AudioFileSource::Flag (0)));
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
|
@ -1110,9 +1110,9 @@ Editor::temporal_zoom_step (bool coarser)
|
|||
nfpu = frames_per_unit;
|
||||
|
||||
if (coarser) {
|
||||
nfpu *= 2.0;
|
||||
nfpu *= 1.61803399;
|
||||
} else {
|
||||
nfpu = max(1.0,(nfpu/2.0));
|
||||
nfpu = max(1.0,(nfpu/1.61803399));
|
||||
}
|
||||
|
||||
temporal_zoom (nfpu);
|
||||
|
@ -1251,22 +1251,22 @@ Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
|
|||
{
|
||||
if (!session) return;
|
||||
|
||||
jack_nframes_t range_before = frame - leftmost_frame;
|
||||
double range_before = frame - leftmost_frame;
|
||||
double new_fpu;
|
||||
|
||||
new_fpu = frames_per_unit;
|
||||
|
||||
if (coarser) {
|
||||
new_fpu *= 2.0;
|
||||
range_before *= 2;
|
||||
new_fpu *= 1.61803399;
|
||||
range_before *= 1.61803399;
|
||||
} else {
|
||||
new_fpu = max(1.0,(new_fpu/2.0));
|
||||
range_before /= 2;
|
||||
new_fpu = max(1.0,(new_fpu/1.61803399));
|
||||
range_before /= 1.61803399;
|
||||
}
|
||||
|
||||
if (new_fpu == frames_per_unit) return;
|
||||
|
||||
jack_nframes_t new_leftmost = frame - range_before;
|
||||
jack_nframes_t new_leftmost = frame - (jack_nframes_t)range_before;
|
||||
|
||||
if (new_leftmost > frame) new_leftmost = 0;
|
||||
|
||||
|
|
|
@ -819,9 +819,9 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
|
|||
if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
|
||||
lower = lower - spacer;
|
||||
} else {
|
||||
upper = upper + spacer - lower;
|
||||
lower = 0;
|
||||
}
|
||||
upper = upper + spacer;
|
||||
range = (jack_nframes_t) floor (upper - lower);
|
||||
|
||||
if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
|
||||
|
@ -1035,114 +1035,87 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
return 0;
|
||||
}
|
||||
|
||||
TempoMap::BBTPointList::iterator i;
|
||||
TempoMap::BBTPointList *zoomed_bbt_points;
|
||||
TempoMap::BBTPointList::iterator i;
|
||||
|
||||
uint32_t beats = 0;
|
||||
uint32_t bars = 0;
|
||||
uint32_t tick = 0;
|
||||
uint32_t skip;
|
||||
uint32_t t;
|
||||
uint32_t zoomed_beats = 0;
|
||||
uint32_t zoomed_bars = 0;
|
||||
uint32_t desirable_marks;
|
||||
uint32_t magic_accent_number = 1;
|
||||
gint nmarks;
|
||||
char buf[64];
|
||||
gint n;
|
||||
jack_nframes_t pos;
|
||||
jack_nframes_t frame_one_beats_worth;
|
||||
jack_nframes_t frame_skip;
|
||||
double frame_skip_error;
|
||||
double accumulated_error;
|
||||
bool bar_helper_on = true;
|
||||
|
||||
bool bar_helper_on = true;
|
||||
|
||||
BBT_Time previous_beat;
|
||||
BBT_Time next_beat;
|
||||
jack_nframes_t next_beat_pos;
|
||||
jack_nframes_t ilower = (jack_nframes_t) floor (lower);
|
||||
jack_nframes_t iupper = (jack_nframes_t) floor (upper);
|
||||
|
||||
if ((desirable_marks = maxchars / 6) == 0) {
|
||||
if ((desirable_marks = maxchars / 7) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* align the tick marks to whatever we're snapping to... */
|
||||
|
||||
if (snap_type == SnapToAThirdBeat) {
|
||||
|
||||
switch (snap_type) {
|
||||
case SnapToAThirdBeat:
|
||||
bbt_beat_subdivision = 3;
|
||||
} else if (snap_type == SnapToAQuarterBeat) {
|
||||
break;
|
||||
case SnapToAQuarterBeat:
|
||||
bbt_beat_subdivision = 4;
|
||||
} else if (snap_type == SnapToAEighthBeat) {
|
||||
break;
|
||||
case SnapToAEighthBeat:
|
||||
bbt_beat_subdivision = 8;
|
||||
magic_accent_number = 2;
|
||||
} else if (snap_type == SnapToASixteenthBeat) {
|
||||
break;
|
||||
case SnapToASixteenthBeat:
|
||||
bbt_beat_subdivision = 16;
|
||||
magic_accent_number = 4;
|
||||
} else if (snap_type == SnapToAThirtysecondBeat) {
|
||||
break;
|
||||
case SnapToAThirtysecondBeat:
|
||||
bbt_beat_subdivision = 32;
|
||||
magic_accent_number = 8;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
bbt_beat_subdivision = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* First find what a beat's distance is, so we can start plotting stuff before the beginning of the ruler */
|
||||
|
||||
session->bbt_time(ilower,previous_beat);
|
||||
previous_beat.ticks = 0;
|
||||
next_beat = previous_beat;
|
||||
|
||||
if (session->tempo_map().meter_at(ilower).beats_per_bar() < (next_beat.beats + 1)) {
|
||||
next_beat.bars += 1;
|
||||
next_beat.beats = 1;
|
||||
} else {
|
||||
next_beat.beats += 1;
|
||||
}
|
||||
|
||||
frame_one_beats_worth = session->tempo_map().frame_time(next_beat) - session->tempo_map().frame_time(previous_beat);
|
||||
|
||||
|
||||
zoomed_bbt_points = session->tempo_map().get_points((ilower >= frame_one_beats_worth) ? ilower - frame_one_beats_worth : 0, iupper);
|
||||
|
||||
if (current_bbt_points == 0 || zoomed_bbt_points == 0 || zoomed_bbt_points->empty()) {
|
||||
if (current_bbt_points == 0 || current_bbt_points->empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = current_bbt_points->begin(); i != current_bbt_points->end(); i++) {
|
||||
if ((*i).type == TempoMap::Beat) {
|
||||
beats++;
|
||||
} else if ((*i).type == TempoMap::Bar) {
|
||||
bars++;
|
||||
}
|
||||
}
|
||||
i = current_bbt_points->end();
|
||||
i--;
|
||||
bars = (*i).bar - (*current_bbt_points->begin()).bar;
|
||||
beats = current_bbt_points->size() - bars;
|
||||
|
||||
/*Only show the bar helper if there aren't many bars on the screen */
|
||||
if (bars > 1) {
|
||||
if (bars > 2) {
|
||||
bar_helper_on = false;
|
||||
}
|
||||
|
||||
for (i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end(); i++) {
|
||||
if ((*i).type == TempoMap::Beat) {
|
||||
zoomed_beats++;
|
||||
} else if ((*i).type == TempoMap::Bar) {
|
||||
zoomed_bars++;
|
||||
}
|
||||
}
|
||||
|
||||
if (desirable_marks > (beats / 4)) {
|
||||
|
||||
/* we're in beat land...*/
|
||||
|
||||
uint32_t tick = 0;
|
||||
uint32_t skip;
|
||||
uint32_t t;
|
||||
jack_nframes_t frame_skip;
|
||||
double frame_skip_error;
|
||||
double accumulated_error;
|
||||
double position_of_helper;
|
||||
bool i_am_accented = false;
|
||||
bool we_need_ticks = false;
|
||||
|
||||
position_of_helper = ilower + (30 * Editor::get_current_zoom ());
|
||||
|
||||
if (desirable_marks >= (beats * 2)) {
|
||||
nmarks = (zoomed_beats * bbt_beat_subdivision) + 1;
|
||||
if (desirable_marks >= (beats)) {
|
||||
nmarks = ((beats + 1) * bbt_beat_subdivision) + 1;
|
||||
we_need_ticks = true;
|
||||
} else {
|
||||
nmarks = zoomed_beats + 1;
|
||||
nmarks = beats + 1;
|
||||
}
|
||||
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
|
@ -1151,17 +1124,14 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
(*marks)[0].position = ilower;
|
||||
(*marks)[0].style = GtkCustomRulerMarkMicro;
|
||||
|
||||
for (n = 1, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
|
||||
|
||||
if ((*i).frame <= ilower && (bar_helper_on)) {
|
||||
|
||||
for (n = 1, i = current_bbt_points->begin(); n < nmarks && i != current_bbt_points->end(); i++) {
|
||||
|
||||
if ((*i).frame < ilower && (bar_helper_on)) {
|
||||
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
|
||||
(*marks)[0].label = g_strdup (buf);
|
||||
} else {
|
||||
|
||||
|
||||
if ((*i).type == TempoMap::Bar) {
|
||||
tick = 0;
|
||||
(((*i).frame < position_of_helper) && bar_helper_on) ?
|
||||
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
|
||||
(*marks)[n].label = g_strdup (buf);
|
||||
|
@ -1170,7 +1140,6 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
n++;
|
||||
|
||||
} else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
|
||||
tick = 0;
|
||||
((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ?
|
||||
snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
|
||||
if (((*i).beat % 2 == 1) || we_need_ticks) {
|
||||
|
@ -1184,33 +1153,36 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
|
||||
}
|
||||
/* Find the next beat */
|
||||
|
||||
session->bbt_time((*i).frame, next_beat);
|
||||
|
||||
if (session->tempo_map().meter_at((*i).frame).beats_per_bar() > (next_beat.beats + 1)) {
|
||||
next_beat.beats += 1;
|
||||
} else {
|
||||
next_beat.bars += 1;
|
||||
next_beat.beats = 1;
|
||||
}
|
||||
|
||||
next_beat_pos = session->tempo_map().frame_time(next_beat);
|
||||
|
||||
/* Add the tick marks */
|
||||
|
||||
if (we_need_ticks) {
|
||||
if (we_need_ticks && (*i).type != TempoMap::Bar) {
|
||||
|
||||
frame_skip = (jack_nframes_t) floor ((session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
|
||||
frame_skip_error = ((session->frame_rate() * 60.0f) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())) - frame_skip;
|
||||
/* Find the next beat */
|
||||
|
||||
next_beat.beats = (*i).beat;
|
||||
next_beat.bars = (*i).bar;
|
||||
|
||||
if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
|
||||
next_beat.beats += 1;
|
||||
} else {
|
||||
next_beat.bars += 1;
|
||||
next_beat.beats = 1;
|
||||
}
|
||||
|
||||
next_beat_pos = session->tempo_map().frame_time(next_beat);
|
||||
|
||||
frame_skip = (jack_nframes_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
|
||||
frame_skip_error -= frame_skip;
|
||||
skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
|
||||
|
||||
pos = (*i).frame + frame_skip;
|
||||
accumulated_error = frame_skip_error;
|
||||
|
||||
tick += skip;
|
||||
tick = skip;
|
||||
|
||||
for (t = 0; tick < Meter::ticks_per_beat && pos <= next_beat_pos ; pos += frame_skip, tick += skip, ++t) {
|
||||
for (t = 0; (tick < Meter::ticks_per_beat) && (n < nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
|
||||
|
||||
if (t % magic_accent_number == (magic_accent_number - 1)) {
|
||||
i_am_accented = true;
|
||||
|
@ -1247,23 +1219,22 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
}
|
||||
}
|
||||
delete zoomed_bbt_points;
|
||||
return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures
|
||||
|
||||
} else {
|
||||
|
||||
/* we're in bar land */
|
||||
|
||||
if (desirable_marks < (uint32_t) (zoomed_bars / 256)) {
|
||||
if (desirable_marks < (uint32_t) (bars / 256)) {
|
||||
nmarks = 1;
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", zoomed_bars );
|
||||
snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", bars );
|
||||
(*marks)[0].style = GtkCustomRulerMarkMajor;
|
||||
(*marks)[0].label = g_strdup (buf);
|
||||
(*marks)[0].position = ilower;
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint) (zoomed_bars / 64))) {
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint) (bars / 64))) {
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
|
||||
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
|
||||
if ((*i).type == TempoMap::Bar) {
|
||||
if ((*i).bar % 64 == 1) {
|
||||
if ((*i).bar % 256 == 1) {
|
||||
|
@ -1283,9 +1254,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 16))) {
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(bars / 16))) {
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
|
||||
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
|
||||
if ((*i).type == TempoMap::Bar) {
|
||||
if ((*i).bar % 16 == 1) {
|
||||
if ((*i).bar % 64 == 1) {
|
||||
|
@ -1305,9 +1276,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 4))){
|
||||
} else if (desirable_marks < (uint32_t) (nmarks = (gint)(bars / 4))){
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
|
||||
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; ++i) {
|
||||
if ((*i).type == TempoMap::Bar) {
|
||||
if ((*i).bar % 4 == 1) {
|
||||
if ((*i).bar % 16 == 1) {
|
||||
|
@ -1328,9 +1299,9 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
}
|
||||
} else {
|
||||
nmarks = zoomed_bars;
|
||||
nmarks = bars;
|
||||
*marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
|
||||
for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
|
||||
for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
|
||||
if ((*i).type == TempoMap::Bar) {
|
||||
if ((*i).bar % 4 == 1) {
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
|
||||
|
@ -1349,7 +1320,6 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
|
|||
}
|
||||
}
|
||||
}
|
||||
delete zoomed_bbt_points;
|
||||
return nmarks;
|
||||
}
|
||||
}
|
||||
|
@ -1448,9 +1418,9 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
|
|||
if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
|
||||
lower = lower - spacer;
|
||||
} else {
|
||||
upper = upper + spacer;
|
||||
lower = 0;
|
||||
}
|
||||
upper = upper + spacer;
|
||||
range = iupper - ilower;
|
||||
|
||||
if (range < (fr / 50)) {
|
||||
|
|
|
@ -96,14 +96,36 @@ void
|
|||
Editor::tempo_map_changed (Change ignored)
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::tempo_map_changed), ignored));
|
||||
|
||||
|
||||
BBT_Time previous_beat, next_beat; // the beats previous to the leftmost frame and after the rightmost frame
|
||||
|
||||
session->bbt_time(leftmost_frame, previous_beat);
|
||||
session->bbt_time(leftmost_frame + current_page_frames(), next_beat);
|
||||
|
||||
if (previous_beat.beats > 1) {
|
||||
previous_beat.beats -= 1;
|
||||
} else if (previous_beat.bars > 1) {
|
||||
previous_beat.bars--;
|
||||
previous_beat.beats += 1;
|
||||
}
|
||||
previous_beat.ticks = 0;
|
||||
|
||||
if (session->tempo_map().meter_at(leftmost_frame + current_page_frames()).beats_per_bar () > next_beat.beats + 1) {
|
||||
next_beat.beats += 1;
|
||||
} else {
|
||||
next_beat.bars += 1;
|
||||
next_beat.beats = 1;
|
||||
}
|
||||
next_beat.ticks = 0;
|
||||
|
||||
if (current_bbt_points) {
|
||||
delete current_bbt_points;
|
||||
delete current_bbt_points;
|
||||
current_bbt_points = 0;
|
||||
}
|
||||
|
||||
if (session) {
|
||||
current_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames());
|
||||
current_bbt_points = session->tempo_map().get_points (session->tempo_map().frame_time (previous_beat), session->tempo_map().frame_time (next_beat));
|
||||
update_tempo_based_rulers ();
|
||||
} else {
|
||||
current_bbt_points = 0;
|
||||
}
|
||||
|
@ -114,11 +136,11 @@ Editor::tempo_map_changed (Change ignored)
|
|||
void
|
||||
Editor::redisplay_tempo ()
|
||||
{
|
||||
hide_measures ();
|
||||
|
||||
if (session && current_bbt_points) {
|
||||
draw_measures ();
|
||||
update_tempo_based_rulers ();
|
||||
Glib::signal_idle().connect (mem_fun (*this, &Editor::lazy_hide_and_draw_measures));
|
||||
} else {
|
||||
hide_measures ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +148,7 @@ void
|
|||
Editor::hide_measures ()
|
||||
{
|
||||
for (TimeLineList::iterator i = used_measure_lines.begin(); i != used_measure_lines.end(); ++i) {
|
||||
(*i)->hide();
|
||||
(*i)->hide();
|
||||
free_measure_lines.push_back (*i);
|
||||
}
|
||||
used_measure_lines.clear ();
|
||||
|
@ -149,6 +171,14 @@ Editor::get_time_line ()
|
|||
return line;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::lazy_hide_and_draw_measures ()
|
||||
{
|
||||
hide_measures ();
|
||||
draw_measures ();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::draw_measures ()
|
||||
{
|
||||
|
@ -156,86 +186,63 @@ Editor::draw_measures ()
|
|||
return;
|
||||
}
|
||||
|
||||
TempoMap::BBTPointList::iterator i = current_bbt_points->begin();
|
||||
TempoMap::BBTPoint& p = (*i);
|
||||
TempoMap::BBTPointList::iterator i;
|
||||
ArdourCanvas::SimpleLine *line;
|
||||
gdouble xpos, last_xpos;
|
||||
uint32_t cnt;
|
||||
gdouble xpos;
|
||||
double x1, x2, y1, y2, beat_density;
|
||||
|
||||
uint32_t beats = 0;
|
||||
uint32_t bars = 0;
|
||||
uint32_t color;
|
||||
|
||||
if (current_bbt_points == 0 || current_bbt_points->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
last_xpos = 0;
|
||||
track_canvas.get_scroll_region (x1, y1, x2, y2);
|
||||
|
||||
/* get the first bar spacing */
|
||||
|
||||
gdouble last_beat = DBL_MAX;
|
||||
gdouble beat_spacing = 0;
|
||||
i = current_bbt_points->end();
|
||||
i--;
|
||||
bars = (*i).bar - (*current_bbt_points->begin()).bar;
|
||||
beats = current_bbt_points->size() - bars;
|
||||
|
||||
for (i = current_bbt_points->begin(); i != current_bbt_points->end() && beat_spacing == 0; ++i) {
|
||||
TempoMap::BBTPoint& p = (*i);
|
||||
beat_density = (beats * 10.0f) / track_canvas.get_width ();
|
||||
|
||||
switch (p.type) {
|
||||
case TempoMap::Bar:
|
||||
break;
|
||||
|
||||
case TempoMap::Beat:
|
||||
xpos = frame_to_unit (p.frame);
|
||||
if (last_beat < xpos) {
|
||||
beat_spacing = xpos - last_beat;
|
||||
}
|
||||
last_beat = xpos;
|
||||
}
|
||||
}
|
||||
|
||||
if (beat_spacing < 3.0) {
|
||||
/* if the lines are too close together, they become useless */
|
||||
if (beat_density > 2.0f) {
|
||||
/* if the lines are too close together, they become useless */
|
||||
return;
|
||||
}
|
||||
|
||||
double x1, x2, y1, y2;
|
||||
track_canvas.get_scroll_region (x1, y1, x2, y2);
|
||||
y2 = 1000000000.0f;
|
||||
|
||||
|
||||
for (i = current_bbt_points->begin(); i != current_bbt_points->end(); ++i) {
|
||||
|
||||
p = (*i);
|
||||
|
||||
switch (p.type) {
|
||||
switch ((*i).type) {
|
||||
case TempoMap::Bar:
|
||||
break;
|
||||
|
||||
case TempoMap::Beat:
|
||||
xpos = frame_to_unit (p.frame);
|
||||
|
||||
if (p.beat == 1) {
|
||||
if ((*i).beat == 1) {
|
||||
color = color_map[cMeasureLineBeat];
|
||||
} else {
|
||||
color = color_map[cMeasureLineBar];
|
||||
|
||||
/* only draw beat lines if the gaps between beats
|
||||
are large.
|
||||
*/
|
||||
/* only draw beat lines if the gaps between beats are large. */
|
||||
|
||||
if (beat_spacing < 4.0) {
|
||||
break;
|
||||
if (beat_density > 0.25) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt == 0 || xpos - last_xpos > 4.0) {
|
||||
line = get_time_line ();
|
||||
line->property_x1() = xpos;
|
||||
line->property_x2() = xpos;
|
||||
line->property_y2() = y2;
|
||||
line->property_color_rgba() = color;
|
||||
line->raise_to_top();
|
||||
line->show();
|
||||
last_xpos = xpos;
|
||||
++cnt;
|
||||
}
|
||||
|
||||
xpos = frame_to_unit ((*i).frame);
|
||||
line = get_time_line ();
|
||||
line->property_x1() = xpos;
|
||||
line->property_x2() = xpos;
|
||||
line->property_y2() = y2;
|
||||
line->property_color_rgba() = color;
|
||||
//line->raise_to_top();
|
||||
line->show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -244,6 +251,7 @@ Editor::draw_measures ()
|
|||
|
||||
cursor_group->raise_to_top();
|
||||
time_line_group->lower_to_bottom();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -183,8 +183,8 @@ MidiStreamView::setup_rec_box ()
|
|||
assert(region);
|
||||
region->set_position (_trackview.session().transport_frame(), this);
|
||||
rec_regions.push_back (region);
|
||||
/* catch it if it goes away */
|
||||
region->GoingAway.connect (bind (mem_fun (*this, &MidiStreamView::remove_rec_region), region));
|
||||
|
||||
// rec regions are destroyed in setup_rec_box
|
||||
|
||||
/* we add the region later */
|
||||
}
|
||||
|
@ -252,6 +252,15 @@ MidiStreamView::setup_rec_box ()
|
|||
last_rec_data_frame = 0;
|
||||
|
||||
/* remove temp regions */
|
||||
|
||||
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) {
|
||||
list<boost::shared_ptr<Region> >::iterator tmp;
|
||||
tmp = iter;
|
||||
++tmp;
|
||||
(*iter)->drop_references ();
|
||||
iter = tmp;
|
||||
}
|
||||
|
||||
rec_regions.clear();
|
||||
|
||||
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";
|
||||
|
|
|
@ -657,8 +657,8 @@ NewSessionDialog::reset_template()
|
|||
void
|
||||
NewSessionDialog::reset_recent()
|
||||
{
|
||||
/* Shamelessly ripped from ardour_ui.cc */
|
||||
std::vector<string *> *sessions;
|
||||
/* Shamelessly ripped from ardour_ui.cc */
|
||||
std::vector<string *> *sessions;
|
||||
std::vector<string *>::iterator i;
|
||||
RecentSessionsSorter cmp;
|
||||
|
||||
|
@ -677,7 +677,7 @@ NewSessionDialog::reset_recent()
|
|||
|
||||
for (i = sessions->begin(); i != sessions->end(); ++i) {
|
||||
|
||||
std::vector<std::string*>* states;
|
||||
std::vector<std::string*>* states;
|
||||
std::vector<const gchar*> item;
|
||||
std::string fullpath = *(*i);
|
||||
|
||||
|
@ -699,7 +699,7 @@ NewSessionDialog::reset_recent()
|
|||
row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
|
||||
row[recent_columns.fullpath] = fullpath;
|
||||
|
||||
if (states->size() > 1) {
|
||||
if (states->size()) {
|
||||
|
||||
/* add the children */
|
||||
|
||||
|
|
|
@ -152,7 +152,6 @@ OptionEditor::set_session (Session *s)
|
|||
click_emphasis_path_entry.set_sensitive (false);
|
||||
session_raid_entry.set_sensitive (false);
|
||||
|
||||
smpte_fps_combo.set_sensitive (false);
|
||||
short_xfade_slider.set_sensitive (false);
|
||||
smpte_offset_negative_button.set_sensitive (false);
|
||||
|
||||
|
@ -165,28 +164,9 @@ OptionEditor::set_session (Session *s)
|
|||
click_path_entry.set_sensitive (true);
|
||||
click_emphasis_path_entry.set_sensitive (true);
|
||||
session_raid_entry.set_sensitive (true);
|
||||
smpte_fps_combo.set_sensitive (true);
|
||||
short_xfade_slider.set_sensitive (true);
|
||||
smpte_offset_negative_button.set_sensitive (true);
|
||||
|
||||
if (!s->smpte_drop_frames) {
|
||||
// non-drop frames
|
||||
if (s->smpte_frames_per_second == 24.0)
|
||||
smpte_fps_combo.set_active_text (_("24 FPS"));
|
||||
else if (s->smpte_frames_per_second == 25.0)
|
||||
smpte_fps_combo.set_active_text (_("25 FPS"));
|
||||
else if (s->smpte_frames_per_second == 30.0)
|
||||
smpte_fps_combo.set_active_text (_("30 FPS"));
|
||||
else
|
||||
smpte_fps_combo.set_active_text (_("???"));
|
||||
} else {
|
||||
// drop frames
|
||||
if (floor(s->smpte_frames_per_second) == 29.0)
|
||||
smpte_fps_combo.set_active_text (_("30 FPS drop"));
|
||||
else
|
||||
smpte_fps_combo.set_active_text (_("???"));
|
||||
}
|
||||
|
||||
smpte_offset_clock.set_session (s);
|
||||
smpte_offset_clock.set (s->smpte_offset (), true);
|
||||
|
||||
|
@ -352,15 +332,6 @@ OptionEditor::setup_sync_options ()
|
|||
HBox* hbox;
|
||||
vector<string> dumb;
|
||||
|
||||
dumb.clear ();
|
||||
dumb.push_back (X_("24 FPS"));
|
||||
dumb.push_back (X_("25 FPS"));
|
||||
dumb.push_back (X_("30 FPS drop"));
|
||||
dumb.push_back (X_("30 FPS non-drop"));
|
||||
|
||||
set_popdown_strings (smpte_fps_combo, dumb);
|
||||
smpte_fps_combo.signal_changed().connect (mem_fun(*this, &OptionEditor::smpte_fps_chosen));
|
||||
|
||||
smpte_offset_clock.set_mode (AudioClock::SMPTE);
|
||||
smpte_offset_clock.ValueChanged.connect (mem_fun(*this, &OptionEditor::smpte_offset_chosen));
|
||||
|
||||
|
@ -368,19 +339,9 @@ OptionEditor::setup_sync_options ()
|
|||
|
||||
smpte_offset_negative_button.unset_flags (Gtk::CAN_FOCUS);
|
||||
|
||||
Label *smpte_fps_label = manage (new Label (_("SMPTE Frames/second")));
|
||||
Label *smpte_offset_label = manage (new Label (_("SMPTE Offset")));
|
||||
smpte_fps_label->set_name("OptionsLabel");
|
||||
smpte_offset_label->set_name("OptionsLabel");
|
||||
|
||||
hbox = manage (new HBox);
|
||||
hbox->set_border_width (5);
|
||||
hbox->set_spacing (10);
|
||||
hbox->pack_start (*smpte_fps_label, false, false);
|
||||
hbox->pack_start (smpte_fps_combo, false, false);
|
||||
|
||||
sync_packer.pack_start (*hbox, false, false);
|
||||
|
||||
hbox = manage (new HBox);
|
||||
hbox->set_border_width (5);
|
||||
hbox->set_spacing (10);
|
||||
|
@ -401,24 +362,6 @@ OptionEditor::smpte_offset_negative_clicked ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
OptionEditor::smpte_fps_chosen ()
|
||||
{
|
||||
if (session) {
|
||||
string str = smpte_fps_combo.get_active_text();
|
||||
|
||||
if (str == X_("24 FPS")) {
|
||||
session->set_smpte_type (24.0, false);
|
||||
} else if (str == X_("25 FPS")) {
|
||||
session->set_smpte_type (25.0, false);
|
||||
} else if (str == X_("30 FPS drop")) {
|
||||
session->set_smpte_type (29.97, true);
|
||||
} else if (str == X_("30 FPS non-drop")) {
|
||||
session->set_smpte_type (30.0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OptionEditor::smpte_offset_chosen()
|
||||
{
|
||||
|
|
|
@ -100,13 +100,11 @@ class OptionEditor : public Gtk::Dialog
|
|||
Gtk::VBox sync_packer;
|
||||
|
||||
Gtk::ComboBoxText slave_type_combo;
|
||||
Gtk::ComboBoxText smpte_fps_combo;
|
||||
AudioClock smpte_offset_clock;
|
||||
Gtk::CheckButton smpte_offset_negative_button;
|
||||
|
||||
void setup_sync_options ();
|
||||
|
||||
void smpte_fps_chosen ();
|
||||
void smpte_offset_chosen ();
|
||||
void smpte_offset_negative_clicked ();
|
||||
|
||||
|
|
|
@ -26,16 +26,12 @@ class AudioRegionGainLine : public AutomationLine
|
|||
|
||||
void remove_point (ControlPoint&);
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
|
||||
|
||||
private:
|
||||
ARDOUR::Session& session;
|
||||
AudioRegionView& rv;
|
||||
|
||||
UndoAction get_memento();
|
||||
|
||||
PBD::ID _id;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -118,18 +118,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
|
||||
hide_button.add (*(manage (new Image (get_xpm("small_x.xpm")))));
|
||||
|
||||
solo_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
mute_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
playlist_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
automation_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
size_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
visual_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
hide_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
|
||||
solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
|
||||
solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
|
||||
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
|
||||
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
|
||||
edit_group_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::edit_click), false);
|
||||
playlist_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::playlist_click));
|
||||
automation_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::automation_click));
|
||||
|
@ -137,10 +125,14 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click));
|
||||
hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click));
|
||||
|
||||
solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
|
||||
solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
|
||||
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
|
||||
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
|
||||
|
||||
if (is_track()) {
|
||||
rec_enable_button->set_active (false);
|
||||
rec_enable_button->set_name ("TrackRecordEnableButton");
|
||||
rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
|
||||
rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
|
||||
controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
|
||||
ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
|
||||
|
@ -197,6 +189,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
_route->name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
|
||||
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
||||
|
||||
|
||||
if (is_track()) {
|
||||
|
||||
track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen));
|
||||
|
@ -215,6 +208,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
|
||||
editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
|
||||
ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler));
|
||||
|
||||
}
|
||||
|
||||
RouteTimeAxisView::~RouteTimeAxisView ()
|
||||
|
@ -605,19 +599,19 @@ RouteTimeAxisView::set_height (TrackHeight h)
|
|||
show_name_entry ();
|
||||
hide_name_label ();
|
||||
|
||||
mute_button->show_all();
|
||||
solo_button->show_all();
|
||||
mute_button->show();
|
||||
solo_button->show();
|
||||
if (rec_enable_button)
|
||||
rec_enable_button->show_all();
|
||||
rec_enable_button->show();
|
||||
|
||||
edit_group_button.show_all();
|
||||
hide_button.show_all();
|
||||
visual_button.show_all();
|
||||
size_button.show_all();
|
||||
automation_button.show_all();
|
||||
edit_group_button.show();
|
||||
hide_button.show();
|
||||
visual_button.show();
|
||||
size_button.show();
|
||||
automation_button.show();
|
||||
|
||||
if (is_track() && track()->mode() == ARDOUR::Normal) {
|
||||
playlist_button.show_all();
|
||||
playlist_button.show();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -625,10 +619,10 @@ RouteTimeAxisView::set_height (TrackHeight h)
|
|||
show_name_entry ();
|
||||
hide_name_label ();
|
||||
|
||||
mute_button->show_all();
|
||||
solo_button->show_all();
|
||||
mute_button->show();
|
||||
solo_button->show();
|
||||
if (rec_enable_button)
|
||||
rec_enable_button->show_all();
|
||||
rec_enable_button->show();
|
||||
|
||||
edit_group_button.hide ();
|
||||
hide_button.hide ();
|
||||
|
@ -1193,13 +1187,6 @@ RouteTimeAxisView::color_handler (ColorID id, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RouteTimeAxisView::select_me (GdkEventButton* ev)
|
||||
{
|
||||
editor.get_selection().add (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::show_all_automation ()
|
||||
{
|
||||
|
|
|
@ -214,8 +214,7 @@ protected:
|
|||
void map_frozen ();
|
||||
|
||||
void color_handler (ColorID, uint32_t);
|
||||
bool select_me (GdkEventButton*);
|
||||
|
||||
|
||||
void region_view_added (RegionView*);
|
||||
void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
|
|||
|
||||
update_rec_display ();
|
||||
}
|
||||
|
||||
|
||||
mute_button->unset_flags (Gtk::CAN_FOCUS);
|
||||
solo_button->unset_flags (Gtk::CAN_FOCUS);
|
||||
|
||||
|
||||
/* map the current state */
|
||||
|
||||
map_frozen ();
|
||||
|
@ -100,7 +100,7 @@ RouteUI::~RouteUI()
|
|||
delete mute_menu;
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
RouteUI::mute_press(GdkEventButton* ev)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
|
@ -161,7 +161,7 @@ RouteUI::mute_press(GdkEventButton* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
RouteUI::mute_release(GdkEventButton* ev)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
|
@ -175,7 +175,7 @@ RouteUI::mute_release(GdkEventButton* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
RouteUI::solo_press(GdkEventButton* ev)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
|
@ -255,7 +255,7 @@ RouteUI::solo_press(GdkEventButton* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
RouteUI::solo_release(GdkEventButton* ev)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
|
@ -271,7 +271,7 @@ RouteUI::solo_release(GdkEventButton* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
gint
|
||||
bool
|
||||
RouteUI::rec_enable_press(GdkEventButton* ev)
|
||||
{
|
||||
if (!ignore_toggle && is_track() && rec_enable_button) {
|
||||
|
|
|
@ -90,11 +90,11 @@ class RouteUI : public virtual AxisView
|
|||
|
||||
XMLNode* get_child_xml_node (const string & childname);
|
||||
|
||||
gint mute_press(GdkEventButton*);
|
||||
gint mute_release(GdkEventButton*);
|
||||
gint solo_press(GdkEventButton*);
|
||||
gint solo_release(GdkEventButton*);
|
||||
gint rec_enable_press(GdkEventButton*);
|
||||
bool mute_press(GdkEventButton*);
|
||||
bool mute_release(GdkEventButton*);
|
||||
bool solo_press(GdkEventButton*);
|
||||
bool solo_release(GdkEventButton*);
|
||||
bool rec_enable_press(GdkEventButton*);
|
||||
|
||||
void solo_changed(void*);
|
||||
void mute_changed(void*);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <ardour/source_factory.h>
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "editing.h"
|
||||
#include "gui_thread.h"
|
||||
#include "prompter.h"
|
||||
#include "sfdb_ui.h"
|
||||
|
@ -197,7 +198,7 @@ SoundFileBox::play_btn_clicked ()
|
|||
|
||||
for (int n = 0; n < sf_info.channels; ++n) {
|
||||
try {
|
||||
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
|
||||
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
|
||||
srclist.push_back(afs);
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
|
@ -305,6 +306,15 @@ SoundFileBox::field_selected ()
|
|||
}
|
||||
}
|
||||
|
||||
// this needs to be kept in sync with the ImportMode enum defined in editing.h and editing_syms.h.
|
||||
static const char *import_mode_strings[] = {
|
||||
X_("Add to Region list"),
|
||||
X_("Add to selected Track(s)"),
|
||||
X_("Add as new Track(s)"),
|
||||
X_("Add as new Tape Track(s)"),
|
||||
0
|
||||
};
|
||||
|
||||
SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
|
||||
: ArdourDialog (title, false),
|
||||
chooser (Gtk::FILE_CHOOSER_ACTION_OPEN)
|
||||
|
@ -339,13 +349,6 @@ SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
|
|||
show_all ();
|
||||
}
|
||||
|
||||
static const char *import_mode_strings[] = {
|
||||
X_("Add to Region list"),
|
||||
X_("Add as new Track(s)"),
|
||||
X_("Add to selected Track(s)"),
|
||||
0
|
||||
};
|
||||
|
||||
vector<string> SoundFileOmega::mode_strings;
|
||||
|
||||
SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s)
|
||||
|
|
|
@ -178,6 +178,8 @@ StreamView::remove_region_view (boost::shared_ptr<Region> r)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
(unused)
|
||||
void
|
||||
StreamView::remove_rec_region (boost::shared_ptr<Region> r)
|
||||
{
|
||||
|
@ -195,6 +197,7 @@ StreamView::remove_rec_region (boost::shared_ptr<Region> r)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
StreamView::undisplay_diskstream ()
|
||||
|
|
|
@ -109,7 +109,7 @@ protected:
|
|||
|
||||
virtual void add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves) = 0;
|
||||
virtual void remove_region_view (boost::shared_ptr<ARDOUR::Region> );
|
||||
void remove_rec_region (boost::shared_ptr<ARDOUR::Region>);
|
||||
//void remove_rec_region (boost::shared_ptr<ARDOUR::Region>); (unused)
|
||||
|
||||
void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
|
||||
virtual void undisplay_diskstream ();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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__
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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__
|
|
@ -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;
|
|
@ -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__
|
|
@ -171,9 +171,27 @@ def CheckJackRecomputeLatencies(context):
|
|||
context.Result(result)
|
||||
return result
|
||||
|
||||
jack_video_frame_offset_test = """
|
||||
#include <jack/transport.h>
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
jack_position_t pos;
|
||||
|
||||
pos.valid & JackVideoFrameOffset;
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
|
||||
def CheckJackVideoFrameOffset(context):
|
||||
context.Message('Checking for JackVideoFrameOffset in jack_position_bits_t enum...')
|
||||
result = context.TryLink(jack_video_frame_offset_test, '.c')
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
conf = Configure(ardour, custom_tests = {
|
||||
'CheckJackClientOpen' : CheckJackClientOpen,
|
||||
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies
|
||||
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
|
||||
'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset
|
||||
})
|
||||
|
||||
if conf.CheckJackClientOpen():
|
||||
|
@ -182,6 +200,14 @@ if conf.CheckJackClientOpen():
|
|||
if conf.CheckJackRecomputeLatencies():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES")
|
||||
|
||||
if conf.CheckJackVideoFrameOffset():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_VIDEO_SUPPORT")
|
||||
|
||||
if conf.CheckFunc('jack_port_ensure_monitor'):
|
||||
env.Append(CCFLAGS='-DHAVE_JACK_PORT_ENSURE_MONITOR')
|
||||
else:
|
||||
print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
|
||||
|
||||
#
|
||||
# Optional header files
|
||||
#
|
||||
|
|
|
@ -61,8 +61,6 @@ class AudioDiskstream : public Diskstream
|
|||
AudioDiskstream (Session &, const XMLNode&);
|
||||
~AudioDiskstream();
|
||||
|
||||
const PBD::ID& id() const { return _id; }
|
||||
|
||||
float playback_buffer_load() const;
|
||||
float capture_buffer_load() const;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class AudioFileSource : public AudioSource {
|
|||
|
||||
int move_to_trash (const string trash_dir_name);
|
||||
|
||||
static bool is_empty (string path);
|
||||
static bool is_empty (Session&, string path);
|
||||
void mark_streaming_write_completed ();
|
||||
|
||||
void mark_take (string);
|
||||
|
@ -104,16 +104,16 @@ class AudioFileSource : public AudioSource {
|
|||
|
||||
/* constructor to be called for existing external-to-session files */
|
||||
|
||||
AudioFileSource (std::string path, Flag flags);
|
||||
AudioFileSource (Session&, std::string path, Flag flags);
|
||||
|
||||
/* constructor to be called for new in-session files */
|
||||
|
||||
AudioFileSource (std::string path, Flag flags,
|
||||
AudioFileSource (Session&, std::string path, Flag flags,
|
||||
SampleFormat samp_format, HeaderFormat hdr_format);
|
||||
|
||||
/* constructor to be called for existing in-session files */
|
||||
|
||||
AudioFileSource (const XMLNode&);
|
||||
AudioFileSource (Session&, const XMLNode&);
|
||||
|
||||
int init (string idstr, bool must_exist);
|
||||
|
||||
|
@ -121,7 +121,6 @@ class AudioFileSource : public AudioSource {
|
|||
string _path;
|
||||
Flag _flags;
|
||||
string _take_id;
|
||||
bool allow_remove_if_empty;
|
||||
uint64_t timeline_position;
|
||||
|
||||
static string peak_dir;
|
||||
|
|
|
@ -111,6 +111,8 @@ class AudioPlaylist : public ARDOUR::Playlist
|
|||
bool region_changed (Change, boost::shared_ptr<Region>);
|
||||
void crossfade_changed (Change);
|
||||
void add_crossfade (Crossfade&);
|
||||
|
||||
void source_offset_changed (boost::shared_ptr<AudioRegion> region);
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
|
|
@ -174,6 +174,7 @@ class AudioRegion : public Region
|
|||
void recompute_at_end ();
|
||||
|
||||
void envelope_changed (Change);
|
||||
void source_offset_changed ();
|
||||
|
||||
mutable Curve _fade_in;
|
||||
FadeShape _fade_in_shape;
|
||||
|
|
|
@ -47,8 +47,8 @@ const jack_nframes_t frames_per_peak = 256;
|
|||
class AudioSource : public Source
|
||||
{
|
||||
public:
|
||||
AudioSource (string name);
|
||||
AudioSource (const XMLNode&);
|
||||
AudioSource (Session&, string name);
|
||||
AudioSource (Session&, const XMLNode&);
|
||||
virtual ~AudioSource ();
|
||||
|
||||
virtual jack_nframes_t available_peaks (double zoom) const;
|
||||
|
|
|
@ -159,8 +159,6 @@ struct ControlEvent {
|
|||
XMLNode &get_state(void);
|
||||
int set_state (const XMLNode &s);
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
|
||||
void set_max_xval (double);
|
||||
double get_max_xval() const { return max_xval; }
|
||||
|
||||
|
@ -189,7 +187,7 @@ struct ControlEvent {
|
|||
static sigc::signal<void, AutomationList*> AutomationListCreated;
|
||||
|
||||
protected:
|
||||
PBD::ID _id;
|
||||
|
||||
struct State : public ARDOUR::StateManager::State {
|
||||
AutomationEventList events;
|
||||
|
||||
|
|
|
@ -20,15 +20,16 @@
|
|||
#ifndef __coreaudio_source_h__
|
||||
#define __coreaudio_source_h__
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
|
||||
#include <ardour/audiofilesource.h>
|
||||
#include <AudioToolbox/ExtendedAudioFile.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class CoreAudioSource : public AudioFileSource {
|
||||
public:
|
||||
CoreAudioSource (const XMLNode&);
|
||||
CoreAudioSource (const string& path_plus_channel, Flag);
|
||||
CoreAudioSource (ARDOUR::Session&, const XMLNode&);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag);
|
||||
~CoreAudioSource ();
|
||||
|
||||
float sample_rate() const;
|
||||
|
@ -45,7 +46,7 @@ class CoreAudioSource : public AudioFileSource {
|
|||
|
||||
|
||||
private:
|
||||
ExtAudioFileRef af;
|
||||
mutable CAAudioFile af;
|
||||
uint16_t n_channels;
|
||||
|
||||
mutable float *tmpbuf;
|
||||
|
|
|
@ -31,12 +31,12 @@ namespace ARDOUR {
|
|||
|
||||
class DestructiveFileSource : public SndFileSource {
|
||||
public:
|
||||
DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
|
||||
DestructiveFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
|
||||
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
|
||||
|
||||
DestructiveFileSource (std::string path, Flag flags);
|
||||
DestructiveFileSource (Session&, std::string path, Flag flags);
|
||||
|
||||
DestructiveFileSource (const XMLNode&);
|
||||
DestructiveFileSource (Session&, const XMLNode&);
|
||||
~DestructiveFileSource ();
|
||||
|
||||
jack_nframes_t last_capture_start_frame() const;
|
||||
|
|
|
@ -92,7 +92,6 @@ class IO;
|
|||
bool destructive() const { return _flags & Destructive; }
|
||||
virtual void set_destructive (bool yn);
|
||||
|
||||
const PBD::ID& id() const { return _id; }
|
||||
bool hidden() const { return _flags & Hidden; }
|
||||
bool recordable() const { return _flags & Recordable; }
|
||||
bool reversed() const { return _actual_speed < 0.0f; }
|
||||
|
@ -243,7 +242,6 @@ class IO;
|
|||
ARDOUR::Session& _session;
|
||||
ARDOUR::IO* _io;
|
||||
ChanCount _n_channels;
|
||||
PBD::ID _id;
|
||||
Playlist* _playlist;
|
||||
|
||||
mutable gint _record_enabled;
|
||||
|
|
|
@ -263,8 +263,6 @@ public:
|
|||
void start_pan_touch (uint32_t which);
|
||||
void end_pan_touch (uint32_t which);
|
||||
|
||||
const PBD::ID& id() const { return _id; }
|
||||
|
||||
void defer_pan_reset ();
|
||||
void allow_pan_reset ();
|
||||
|
||||
|
@ -292,7 +290,6 @@ public:
|
|||
string _name;
|
||||
Connection* _input_connection;
|
||||
Connection* _output_connection;
|
||||
PBD::ID _id;
|
||||
bool no_panner_reset;
|
||||
bool _phase_invert;
|
||||
XMLNode* deferred_state;
|
||||
|
|
|
@ -121,10 +121,7 @@ class Location : public sigc::trackable, public PBD::StatefulDestructible
|
|||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
|
||||
private:
|
||||
PBD::ID _id;
|
||||
string _name;
|
||||
jack_nframes_t _start;
|
||||
jack_nframes_t _end;
|
||||
|
@ -150,7 +147,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
|
|||
|
||||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&);
|
||||
PBD::ID id() { return _id; }
|
||||
Location *get_location_by_id(PBD::ID);
|
||||
|
||||
Location* auto_loop_location () const;
|
||||
|
@ -204,8 +200,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
|
|||
|
||||
Change restore_state (StateManager::State&);
|
||||
StateManager::State* state_factory (std::string why) const;
|
||||
|
||||
PBD::ID _id;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -43,8 +43,8 @@ class MidiRingBuffer;
|
|||
class MidiSource : public Source
|
||||
{
|
||||
public:
|
||||
MidiSource (string name);
|
||||
MidiSource (const XMLNode&);
|
||||
MidiSource (Session& session, string name);
|
||||
MidiSource (Session& session, const XMLNode&);
|
||||
virtual ~MidiSource ();
|
||||
|
||||
virtual jack_nframes_t read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const;
|
||||
|
|
|
@ -81,7 +81,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
|
|||
EditMode get_edit_mode() const { return _edit_mode; }
|
||||
void set_edit_mode (EditMode);
|
||||
|
||||
PBD::ID id() { return _id; }
|
||||
/* Editing operations */
|
||||
|
||||
void add_region (boost::shared_ptr<Region>, jack_nframes_t position, float times = 1, bool with_save = true);
|
||||
|
@ -279,8 +278,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
|
|||
void unset_freeze_child (Playlist*);
|
||||
|
||||
void timestamp_layer_op (boost::shared_ptr<Region>);
|
||||
|
||||
PBD::ID _id;
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
|
|
@ -103,7 +103,7 @@ class Port : public sigc::trackable {
|
|||
|
||||
void ensure_monitor_input (bool yn) {
|
||||
|
||||
#ifdef WITH_JACK_PORT_ENSURE_MONITOR
|
||||
#ifdef HAVE_JACK_PORT_ENSURE_MONITOR
|
||||
jack_port_ensure_monitor (_port, yn);
|
||||
#else
|
||||
jack_port_request_monitor(_port, yn);
|
||||
|
|
|
@ -37,7 +37,6 @@ class XMLNode;
|
|||
namespace ARDOUR {
|
||||
|
||||
class Playlist;
|
||||
class Source;
|
||||
|
||||
enum RegionEditState {
|
||||
EditChangesNothing = 0,
|
||||
|
@ -99,8 +98,6 @@ class Region : public PBD::StatefulDestructible, public StateManager, public boo
|
|||
|
||||
virtual ~Region();
|
||||
|
||||
const PBD::ID& id() const { return _id; }
|
||||
|
||||
/* Note: changing the name of a Region does not constitute an edit */
|
||||
|
||||
string name() const { return _name; }
|
||||
|
|
|
@ -267,8 +267,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
|
|||
bool dirty() const { return _state_of_the_state & Dirty; }
|
||||
sigc::signal<void> DirtyChanged;
|
||||
|
||||
std::string sound_dir () const;
|
||||
std::string tape_dir () const;
|
||||
std::string sound_dir (bool with_path = true) const;
|
||||
std::string peak_dir () const;
|
||||
std::string dead_sound_dir () const;
|
||||
std::string automation_dir () const;
|
||||
|
@ -281,7 +280,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
|
|||
|
||||
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
|
||||
static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive);
|
||||
static string peak_path_from_audio_path (string);
|
||||
|
||||
string peak_path_from_audio_path (string) const;
|
||||
string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
|
||||
string midi_path_from_name (string);
|
||||
|
||||
|
@ -1713,9 +1713,10 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
|
|||
uint32_t _total_free_4k_blocks;
|
||||
Glib::Mutex space_lock;
|
||||
|
||||
static const char* old_sound_dir_name;
|
||||
static const char* sound_dir_name;
|
||||
static const char* tape_dir_name;
|
||||
static const char* dead_sound_dir_name;
|
||||
static const char* interchange_dir_name;
|
||||
static const char* peak_dir_name;
|
||||
|
||||
string discover_best_sound_dir (bool destructive = false);
|
||||
|
|
|
@ -44,10 +44,10 @@ class SMFSource : public MidiSource {
|
|||
};
|
||||
|
||||
/** Constructor for existing external-to-session files */
|
||||
SMFSource (std::string path, Flag flags = Flag(0));
|
||||
SMFSource (Session& session, std::string path, Flag flags = Flag(0));
|
||||
|
||||
/* Constructor for existing in-session files */
|
||||
SMFSource (const XMLNode&);
|
||||
SMFSource (Session& session, const XMLNode&);
|
||||
|
||||
virtual ~SMFSource ();
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ class SndFileSource : public AudioFileSource {
|
|||
public:
|
||||
/* constructor to be called for existing external-to-session files */
|
||||
|
||||
SndFileSource (std::string path, Flag flags);
|
||||
SndFileSource (Session&, std::string path, Flag flags);
|
||||
|
||||
/* constructor to be called for new in-session files */
|
||||
|
||||
SndFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
|
||||
SndFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
|
||||
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
|
||||
AudioFileSource::Removable|
|
||||
AudioFileSource::RemovableIfEmpty|
|
||||
|
@ -43,7 +43,7 @@ class SndFileSource : public AudioFileSource {
|
|||
|
||||
/* constructor to be called for existing in-session files */
|
||||
|
||||
SndFileSource (const XMLNode&);
|
||||
SndFileSource (Session&, const XMLNode&);
|
||||
|
||||
~SndFileSource ();
|
||||
|
||||
|
|
|
@ -32,11 +32,14 @@
|
|||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Session;
|
||||
|
||||
class Source : public PBD::StatefulDestructible, public sigc::trackable
|
||||
{
|
||||
public:
|
||||
Source (std::string name, DataType type);
|
||||
Source (const XMLNode&);
|
||||
Source (Session&, std::string name, DataType type);
|
||||
Source (Session&, const XMLNode&);
|
||||
|
||||
virtual ~Source ();
|
||||
|
||||
std::string name() const { return _name; }
|
||||
|
@ -44,8 +47,6 @@ class Source : public PBD::StatefulDestructible, public sigc::trackable
|
|||
|
||||
DataType type() { return _type; }
|
||||
|
||||
const PBD::ID& id() const { return _id; }
|
||||
|
||||
time_t timestamp() const { return _timestamp; }
|
||||
void stamp (time_t when) { _timestamp = when; }
|
||||
|
||||
|
@ -65,13 +66,13 @@ class Source : public PBD::StatefulDestructible, public sigc::trackable
|
|||
protected:
|
||||
void update_length (jack_nframes_t pos, jack_nframes_t cnt);
|
||||
|
||||
Session& _session;
|
||||
string _name;
|
||||
DataType _type;
|
||||
time_t _timestamp;
|
||||
jack_nframes_t _length;
|
||||
|
||||
private:
|
||||
PBD::ID _id;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -13,14 +13,17 @@ class XMLNode;
|
|||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Session;
|
||||
|
||||
class SourceFactory {
|
||||
public:
|
||||
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
|
||||
|
||||
static boost::shared_ptr<Source> create (const XMLNode& node);
|
||||
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
|
||||
|
||||
static boost::shared_ptr<Source> createReadable (DataType type, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createWritable (DataType type, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
|
||||
// MIDI sources will have to be hacked in here somehow
|
||||
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -242,7 +242,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
|
|||
|
||||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&);
|
||||
PBD::ID id() { return _id; }
|
||||
|
||||
void dump (std::ostream&) const;
|
||||
void clear ();
|
||||
|
@ -320,8 +319,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
|
|||
|
||||
void save_state (std::string why);
|
||||
|
||||
PBD::ID _id;
|
||||
|
||||
};
|
||||
|
||||
}; /* namespace ARDOUR */
|
||||
|
|
|
@ -1590,7 +1590,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
|
|||
string region_name;
|
||||
_session.region_name (region_name, channels[0].write_source->name(), false);
|
||||
|
||||
cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
|
||||
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Region> rx (RegionFactory::create (srcs, buffer_position, (*ci)->frames, region_name));
|
||||
|
@ -1948,7 +1948,7 @@ AudioDiskstream::use_new_write_source (uint32_t n)
|
|||
|
||||
if (chan.write_source) {
|
||||
|
||||
if (AudioFileSource::is_empty (chan.write_source->path())) {
|
||||
if (AudioFileSource::is_empty (_session, chan.write_source->path())) {
|
||||
chan.write_source->mark_for_remove ();
|
||||
chan.write_source.reset ();
|
||||
} else {
|
||||
|
@ -2185,7 +2185,8 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
|
|||
}
|
||||
|
||||
try {
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, prop->value(), false, _session.frame_rate()));
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, _session, prop->value(), false, _session.frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
|
@ -899,3 +899,4 @@ AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,9 @@ AudioEngine::stop ()
|
|||
bool
|
||||
AudioEngine::get_sync_offset (jack_nframes_t& offset) const
|
||||
{
|
||||
|
||||
#ifdef HAVE_JACK_VIDEO_SUPPORT
|
||||
|
||||
jack_position_t pos;
|
||||
|
||||
(void) jack_transport_query (_jack, &pos);
|
||||
|
@ -176,6 +179,8 @@ AudioEngine::get_sync_offset (jack_nframes_t& offset) const
|
|||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ char AudioFileSource::bwf_country_code[3] = "US";
|
|||
char AudioFileSource::bwf_organization_code[4] = "LAS";
|
||||
char AudioFileSource::bwf_serial_number[13] = "000000000000";
|
||||
|
||||
AudioFileSource::AudioFileSource (string idstr, Flag flags)
|
||||
: AudioSource (idstr), _flags (flags)
|
||||
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
|
||||
: AudioSource (s, idstr), _flags (flags)
|
||||
{
|
||||
/* constructor used for existing external to session files. file must exist already */
|
||||
|
||||
|
@ -74,8 +74,8 @@ AudioFileSource::AudioFileSource (string idstr, Flag flags)
|
|||
|
||||
}
|
||||
|
||||
AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
|
||||
: AudioSource (path), _flags (flags)
|
||||
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
|
||||
: AudioSource (s, path), _flags (flags)
|
||||
{
|
||||
/* constructor used for new internal-to-session files. file cannot exist */
|
||||
|
||||
|
@ -84,8 +84,8 @@ AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat sam
|
|||
}
|
||||
}
|
||||
|
||||
AudioFileSource::AudioFileSource (const XMLNode& node)
|
||||
: AudioSource (node), _flags (Flag (Writable|CanRename))
|
||||
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
|
||||
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
|
||||
{
|
||||
/* constructor used for existing internal-to-session files. file must exist */
|
||||
|
||||
|
@ -101,6 +101,7 @@ AudioFileSource::AudioFileSource (const XMLNode& node)
|
|||
AudioFileSource::~AudioFileSource ()
|
||||
{
|
||||
if (removable()) {
|
||||
cerr << "Removing file " << _path << " because its removable\n";
|
||||
unlink (_path.c_str());
|
||||
unlink (peakpath.c_str());
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ AudioFileSource::~AudioFileSource ()
|
|||
bool
|
||||
AudioFileSource::removable () const
|
||||
{
|
||||
return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_path)));
|
||||
return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -135,7 +136,7 @@ AudioFileSource::init (string pathstr, bool must_exist)
|
|||
string
|
||||
AudioFileSource::peak_path (string audio_path)
|
||||
{
|
||||
return Session::peak_path_from_audio_path (audio_path);
|
||||
return _session.peak_path_from_audio_path (audio_path);
|
||||
}
|
||||
|
||||
string
|
||||
|
@ -527,7 +528,7 @@ void
|
|||
AudioFileSource::set_allow_remove_if_empty (bool yn)
|
||||
{
|
||||
if (writable()) {
|
||||
allow_remove_if_empty = yn;
|
||||
_flags = Flag (_flags | RemovableIfEmpty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,11 +562,12 @@ AudioFileSource::set_name (string newname, bool destructive)
|
|||
}
|
||||
|
||||
bool
|
||||
AudioFileSource::is_empty (string path)
|
||||
AudioFileSource::is_empty (Session& s, string path)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createReadable (DataType::AUDIO, path, NoPeakFile, false));
|
||||
SourceFactory::createReadable (DataType::AUDIO, s, path, NoPeakFile, false));
|
||||
|
||||
if (afs) {
|
||||
ret = (afs->length() == 0);
|
||||
|
|
|
@ -51,7 +51,7 @@ AudioFilter::make_new_sources (boost::shared_ptr<AudioRegion> region, SourceList
|
|||
|
||||
try {
|
||||
nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, path, false, session.frame_rate())));
|
||||
SourceFactory::createWritable (DataType::AUDIO, session, path, false, session.frame_rate())));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <ardour/dB.h>
|
||||
#include <ardour/playlist.h>
|
||||
#include <ardour/audiofilter.h>
|
||||
#include <ardour/audiosource.h>
|
||||
#include <ardour/audiofilesource.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include <locale.h>
|
||||
|
@ -71,6 +71,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
|
|||
_fade_out (0.0, 2.0, 1.0, false),
|
||||
_envelope (0.0, 2.0, 1.0, false)
|
||||
{
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
|
||||
if (afs) {
|
||||
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
|
||||
}
|
||||
|
||||
_scale_amplitude = 1.0;
|
||||
|
||||
set_default_fades ();
|
||||
|
@ -88,6 +93,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
|
|||
, _fade_out (0.0, 2.0, 1.0, false)
|
||||
, _envelope (0.0, 2.0, 1.0, false)
|
||||
{
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
|
||||
if (afs) {
|
||||
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
|
||||
}
|
||||
|
||||
_scale_amplitude = 1.0;
|
||||
|
||||
set_default_fades ();
|
||||
|
@ -180,6 +190,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
|
|||
, _fade_out (0.0, 2.0, 1.0, false)
|
||||
, _envelope (0.0, 2.0, 1.0, false)
|
||||
{
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
|
||||
if (afs) {
|
||||
afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
|
||||
}
|
||||
|
||||
set_default_fades ();
|
||||
|
||||
if (set_state (node)) {
|
||||
|
@ -1165,6 +1180,12 @@ AudioRegion::speed_mismatch (float sr) const
|
|||
return fsr != sr;
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegion::source_offset_changed ()
|
||||
{
|
||||
set_position (source()->natural_position() + start(), this);
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioSource>
|
||||
AudioRegion::audio_source (uint32_t n) const
|
||||
{
|
||||
|
|
|
@ -50,8 +50,8 @@ int AudioSource::peak_request_pipe[2];
|
|||
bool AudioSource::_build_missing_peakfiles = false;
|
||||
bool AudioSource::_build_peakfiles = false;
|
||||
|
||||
AudioSource::AudioSource (string name)
|
||||
: Source (name, DataType::AUDIO)
|
||||
AudioSource::AudioSource (Session& s, string name)
|
||||
: Source (s, name, DataType::AUDIO)
|
||||
{
|
||||
if (pending_peak_sources_lock == 0) {
|
||||
pending_peak_sources_lock = new Glib::Mutex;
|
||||
|
@ -63,8 +63,8 @@ AudioSource::AudioSource (string name)
|
|||
_write_data_count = 0;
|
||||
}
|
||||
|
||||
AudioSource::AudioSource (const XMLNode& node)
|
||||
: Source (node)
|
||||
AudioSource::AudioSource (Session& s, const XMLNode& node)
|
||||
: Source (s, node)
|
||||
{
|
||||
if (pending_peak_sources_lock == 0) {
|
||||
pending_peak_sources_lock = new Glib::Mutex;
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include <pbd/error.h>
|
||||
#include <ardour/coreaudiosource.h>
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
#include <appleutility/CAStreamBasicDescription.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include <AudioToolbox/AudioFormat.h>
|
||||
|
@ -27,14 +30,14 @@
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
CoreAudioSource::CoreAudioSource (const XMLNode& node)
|
||||
: AudioFileSource (node)
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
}
|
||||
|
||||
CoreAudioSource::CoreAudioSource (const string& idstr, Flag flags)
|
||||
: AudioFileSource(idstr, flags)
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags)
|
||||
: AudioFileSource(s, idstr, flags)
|
||||
{
|
||||
init (idstr);
|
||||
}
|
||||
|
@ -43,93 +46,48 @@ void
|
|||
CoreAudioSource::init (const string& idstr)
|
||||
{
|
||||
string::size_type pos;
|
||||
string file;
|
||||
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
af = 0;
|
||||
OSStatus err = noErr;
|
||||
|
||||
_name = idstr;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
file = idstr;
|
||||
_path = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
file = idstr.substr (0, pos);
|
||||
_path = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
FSRef fsr;
|
||||
err = FSPathMakeRef ((UInt8*)file.c_str(), &fsr, 0);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not make reference to file: %1"), name()) << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
err = ExtAudioFileOpen (&fsr, &af);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not open file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
AudioStreamBasicDescription file_asbd;
|
||||
memset(&file_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
size_t asbd_size = sizeof(AudioStreamBasicDescription);
|
||||
err = ExtAudioFileGetProperty(af,
|
||||
kExtAudioFileProperty_FileDataFormat, &asbd_size, &file_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not get file data format for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
n_channels = file_asbd.mChannelsPerFrame;
|
||||
|
||||
cerr << "number of channels: " << n_channels << endl;
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
if (channel >= n_channels) {
|
||||
error << string_compose(_("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number"), n_channels, channel) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
try {
|
||||
af.Open(_path.c_str());
|
||||
|
||||
int64_t ca_frames;
|
||||
size_t prop_size = sizeof(int64_t);
|
||||
CAStreamBasicDescription file_asbd (af.GetFileDataFormat());
|
||||
n_channels = file_asbd.NumberChannels();
|
||||
cerr << "number of channels: " << n_channels << endl;
|
||||
|
||||
if (channel >= n_channels) {
|
||||
error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, channel, name()) << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &prop_size, &ca_frames);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not get file length for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
_length = af.GetNumberFrames();
|
||||
|
||||
_length = ca_frames;
|
||||
_path = file;
|
||||
|
||||
AudioStreamBasicDescription client_asbd;
|
||||
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
client_asbd.mSampleRate = file_asbd.mSampleRate;
|
||||
client_asbd.mFormatID = kAudioFormatLinearPCM;
|
||||
client_asbd.mFormatFlags = kLinearPCMFormatFlagIsFloat;
|
||||
client_asbd.mBytesPerPacket = file_asbd.mChannelsPerFrame * 4;
|
||||
client_asbd.mFramesPerPacket = 1;
|
||||
client_asbd.mBytesPerFrame = client_asbd.mBytesPerPacket;
|
||||
client_asbd.mChannelsPerFrame = file_asbd.mChannelsPerFrame;
|
||||
client_asbd.mBitsPerChannel = 32;
|
||||
|
||||
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not set client data format for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
CAStreamBasicDescription client_asbd(file_asbd);
|
||||
client_asbd.SetCanonical(client_asbd.NumberChannels(), false);
|
||||
af.SetClientFormat (client_asbd);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CoreAudioSource: %1 (%2)", cax.mOperation, name()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (_build_peakfiles) {
|
||||
if (initialize_peakfile (false, file)) {
|
||||
error << string_compose(_("initialize peakfile failed for file %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
if (initialize_peakfile (false, _path)) {
|
||||
error << string_compose("CoreAudioSource: initialize peakfile failed (%1)", name()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
@ -137,41 +95,44 @@ CoreAudioSource::init (const string& idstr)
|
|||
|
||||
CoreAudioSource::~CoreAudioSource ()
|
||||
{
|
||||
cerr << "CoreAudioSource::~CoreAudioSource() " << name() << endl;
|
||||
GoingAway (); /* EMIT SIGNAL */
|
||||
|
||||
if (af) {
|
||||
ExtAudioFileDispose (af);
|
||||
}
|
||||
|
||||
if (tmpbuf) {
|
||||
delete [] tmpbuf;
|
||||
}
|
||||
|
||||
cerr << "deletion done" << endl;
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
err = ExtAudioFileSeek(af, start);
|
||||
if (err != noErr) {
|
||||
error << string_compose(_("CoreAudioSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), err) << endmsg;
|
||||
try {
|
||||
af.Seek (start);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start, _name.substr (1)) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioBufferList abl;
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = n_channels;
|
||||
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst;
|
||||
|
||||
UInt32 new_cnt = cnt;
|
||||
if (n_channels == 1) {
|
||||
err = ExtAudioFileRead(af, (UInt32*) &cnt, &abl);
|
||||
_read_data_count = cnt * sizeof(float);
|
||||
return cnt;
|
||||
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst;
|
||||
try {
|
||||
af.Read (new_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
}
|
||||
_read_data_count = new_cnt * sizeof(float);
|
||||
return new_cnt;
|
||||
}
|
||||
|
||||
uint32_t real_cnt = cnt * n_channels;
|
||||
UInt32 real_cnt = cnt * n_channels;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (_tmpbuf_lock);
|
||||
|
@ -185,10 +146,16 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
|
|||
tmpbuf = new float[tmpbufsize];
|
||||
}
|
||||
|
||||
abl.mBuffers[0].mDataByteSize = real_cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = tmpbuf;
|
||||
|
||||
cerr << "channel: " << channel << endl;
|
||||
|
||||
err = ExtAudioFileRead(af, (UInt32*) &real_cnt, &abl);
|
||||
try {
|
||||
af.Read (real_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
}
|
||||
float *ptr = tmpbuf + channel;
|
||||
real_cnt /= n_channels;
|
||||
|
||||
|
@ -208,15 +175,12 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
|
|||
float
|
||||
CoreAudioSource::sample_rate() const
|
||||
{
|
||||
AudioStreamBasicDescription client_asbd;
|
||||
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
CAStreamBasicDescription client_asbd;
|
||||
|
||||
OSStatus err = noErr;
|
||||
size_t asbd_size = sizeof(AudioStreamBasicDescription);
|
||||
|
||||
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose(_("Could not detect samplerate for: %1"), name()) << endmsg;
|
||||
try {
|
||||
client_asbd = af.GetClientDataFormat ();
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -228,4 +192,3 @@ CoreAudioSource::update_header (jack_nframes_t when, struct tm&, time_t)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,21 +68,21 @@ gain_t* DestructiveFileSource::out_coefficient = 0;
|
|||
gain_t* DestructiveFileSource::in_coefficient = 0;
|
||||
jack_nframes_t DestructiveFileSource::xfade_frames = 64;
|
||||
|
||||
DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
|
||||
: SndFileSource (path, samp_format, hdr_format, rate, flags)
|
||||
DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
|
||||
: SndFileSource (s, path, samp_format, hdr_format, rate, flags)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
|
||||
DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
|
||||
: SndFileSource (path, flags)
|
||||
DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags)
|
||||
: SndFileSource (s, path, flags)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
|
||||
: SndFileSource (node)
|
||||
DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node)
|
||||
: SndFileSource (s, node)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
|
|
@ -375,7 +375,9 @@ ARDOUR::get_user_ardour_path ()
|
|||
|
||||
/* create it if necessary */
|
||||
|
||||
mkdir (path.c_str (), 0755);
|
||||
if (g_mkdir_with_parents (path.c_str (), 0755)) {
|
||||
throw exception ();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ Session::import_audiofile (import_status& status)
|
|||
|
||||
try {
|
||||
newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, buf, false, frame_rate()));
|
||||
SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <algorithm>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
|
@ -2143,8 +2144,8 @@ IO::load_automation (const string& path)
|
|||
fullpath += path;
|
||||
in.open (fullpath.c_str());
|
||||
if (!in) {
|
||||
error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
|
||||
return -1;
|
||||
error << string_compose(_("%1: cannot open automation event file \"%2\" (%2)"), _name, fullpath, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,13 +81,18 @@ Location::set_start (jack_nframes_t s)
|
|||
{
|
||||
if (is_mark()) {
|
||||
if (_start != s) {
|
||||
|
||||
_start = s;
|
||||
_end = s;
|
||||
|
||||
start_changed(this); /* EMIT SIGNAL */
|
||||
|
||||
if ( is_start() ) {
|
||||
|
||||
Session::StartTimeChanged (); /* EMIT SIGNAL */
|
||||
AudioFileSource::set_header_position_offset ( s );
|
||||
}
|
||||
|
||||
if ( is_end() ) {
|
||||
Session::EndTimeChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
|
@ -42,15 +42,15 @@ using namespace PBD;
|
|||
|
||||
sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated;
|
||||
|
||||
MidiSource::MidiSource (string name)
|
||||
: Source (name, DataType::MIDI)
|
||||
MidiSource::MidiSource (Session& s, string name)
|
||||
: Source (s, name, DataType::MIDI)
|
||||
{
|
||||
_read_data_count = 0;
|
||||
_write_data_count = 0;
|
||||
}
|
||||
|
||||
MidiSource::MidiSource (const XMLNode& node)
|
||||
: Source (node)
|
||||
MidiSource::MidiSource (Session& s, const XMLNode& node)
|
||||
: Source (s, node)
|
||||
{
|
||||
_read_data_count = 0;
|
||||
_write_data_count = 0;
|
||||
|
|
|
@ -1090,7 +1090,7 @@ Panner::save () const
|
|||
ofstream out (automation_path.c_str());
|
||||
|
||||
if (!out) {
|
||||
error << string_compose (_("cannot open pan automation file \"%1\" for saving (%s)"), automation_path, strerror (errno))
|
||||
error << string_compose (_("cannot open pan automation file \"%1\" for saving (%2)"), automation_path, strerror (errno))
|
||||
<< endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -224,13 +224,13 @@ Plugin::save_preset (string name, string domain)
|
|||
free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
|
||||
|
||||
string path = string_compose("%1/.%2", envvar, domain);
|
||||
if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
|
||||
if (g_mkdir_with_parents (path.c_str(), 0775)) {
|
||||
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
|
||||
return false;
|
||||
}
|
||||
|
||||
path += "/rdf";
|
||||
if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
|
||||
if (g_mkdir_with_parents (path.c_str(), 0775)) {
|
||||
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -277,17 +277,17 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
-------------------------------------------------------------------------------------------------- */
|
||||
|
||||
if (declick > 0) {
|
||||
Amp::run (bufs, nframes, 0.0, 1.0, _phase_invert);
|
||||
Amp::run (bufs, nframes, 0.0, 1.0, false);
|
||||
_pending_declick = 0;
|
||||
} else if (declick < 0) {
|
||||
Amp::run (bufs, nframes, 1.0, 0.0, _phase_invert);
|
||||
Amp::run (bufs, nframes, 1.0, 0.0, false);
|
||||
_pending_declick = 0;
|
||||
} else {
|
||||
|
||||
/* no global declick */
|
||||
|
||||
if (solo_gain != dsg) {
|
||||
Amp::run (bufs, nframes, solo_gain, dsg, _phase_invert);
|
||||
Amp::run (bufs, nframes, solo_gain, dsg, false);
|
||||
solo_gain = dsg;
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
}
|
||||
|
||||
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, false);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, false);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
}
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, false);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
----------------------------------------------------------------------*/
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Amp::run (bufs, nframes, mute_gain, dmg, false);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
|
|
@ -87,10 +87,11 @@ using boost::shared_ptr;
|
|||
const char* Session::_template_suffix = X_(".template");
|
||||
const char* Session::_statefile_suffix = X_(".ardour");
|
||||
const char* Session::_pending_suffix = X_(".pending");
|
||||
const char* Session::sound_dir_name = X_("sounds");
|
||||
const char* Session::tape_dir_name = X_("tapes");
|
||||
const char* Session::old_sound_dir_name = X_("sounds");
|
||||
const char* Session::sound_dir_name = X_("audiofiles");
|
||||
const char* Session::peak_dir_name = X_("peaks");
|
||||
const char* Session::dead_sound_dir_name = X_("dead_sounds");
|
||||
const char* Session::interchange_dir_name = X_("interchange");
|
||||
|
||||
Session::compute_peak_t Session::compute_peak = 0;
|
||||
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
|
||||
|
@ -2836,17 +2837,11 @@ Session::source_by_id (const PBD::ID& id)
|
|||
}
|
||||
|
||||
string
|
||||
Session::peak_path_from_audio_path (string audio_path)
|
||||
Session::peak_path_from_audio_path (string audio_path) const
|
||||
{
|
||||
/* XXX hardly bombproof! fix me */
|
||||
|
||||
string res;
|
||||
|
||||
res = Glib::path_get_dirname (audio_path);
|
||||
res = Glib::path_get_dirname (res);
|
||||
res += '/';
|
||||
res += peak_dir_name;
|
||||
res += '/';
|
||||
res = peak_dir ();
|
||||
res += PBD::basename_nosuffix (audio_path);
|
||||
res += ".peak";
|
||||
|
||||
|
@ -2992,11 +2987,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
|
|||
|
||||
spath = (*i).path;
|
||||
|
||||
if (destructive) {
|
||||
spath += tape_dir_name;
|
||||
} else {
|
||||
spath += sound_dir_name;
|
||||
}
|
||||
spath += sound_dir (false);
|
||||
|
||||
if (destructive) {
|
||||
if (nchan < 2) {
|
||||
|
@ -3032,9 +3023,10 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
|
|||
}
|
||||
}
|
||||
|
||||
if (access (buf, F_OK) == 0) {
|
||||
if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
|
||||
existing++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (existing == 0) {
|
||||
|
@ -3053,11 +3045,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
|
|||
|
||||
string foo = buf;
|
||||
|
||||
if (destructive) {
|
||||
spath = tape_dir ();
|
||||
} else {
|
||||
spath = discover_best_sound_dir ();
|
||||
}
|
||||
spath = discover_best_sound_dir ();
|
||||
|
||||
string::size_type pos = foo.find_last_of ('/');
|
||||
|
||||
|
@ -3074,7 +3062,8 @@ boost::shared_ptr<AudioFileSource>
|
|||
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
|
||||
{
|
||||
string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive);
|
||||
return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, spath, destructive, frame_rate()));
|
||||
return boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
|
||||
}
|
||||
|
||||
// FIXME: _terrible_ code duplication
|
||||
|
@ -3260,7 +3249,7 @@ Session::create_midi_source_for_session (MidiDiskstream& ds)
|
|||
{
|
||||
string spath = midi_path_from_name (ds.name());
|
||||
|
||||
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, spath, false, frame_rate()));
|
||||
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, spath, false, frame_rate()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3420,17 +3409,35 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
|
|||
void
|
||||
Session::remove_empty_sounds ()
|
||||
{
|
||||
|
||||
PathScanner scanner;
|
||||
string dir;
|
||||
|
||||
dir = sound_dir ();
|
||||
|
||||
vector<string *>* possible_audiofiles = scanner (dir, "\\.wav$", false, true);
|
||||
vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64)$", false, true);
|
||||
|
||||
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
|
||||
Glib::Mutex::Lock lm (source_lock);
|
||||
|
||||
regex_t compiled_tape_track_pattern;
|
||||
int err;
|
||||
|
||||
if (AudioFileSource::is_empty (*(*i))) {
|
||||
if ((err = regcomp (&compiled_tape_track_pattern, "/T[0-9][0-9][0-9][0-9]-", REG_EXTENDED|REG_NOSUB))) {
|
||||
|
||||
char msg[256];
|
||||
|
||||
regerror (err, &compiled_tape_track_pattern, msg, sizeof (msg));
|
||||
|
||||
error << string_compose (_("Cannot compile tape track regexp for use (%1)"), msg) << endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
|
||||
|
||||
/* never remove files that appear to be a tape track */
|
||||
|
||||
if (regexec (&compiled_tape_track_pattern, (*i)->c_str(), 0, 0, 0) == 0) {
|
||||
delete *i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AudioFileSource::is_empty (*this, *(*i))) {
|
||||
|
||||
unlink ((*i)->c_str());
|
||||
|
||||
|
@ -3610,7 +3617,7 @@ jack_nframes_t
|
|||
Session::available_capture_duration ()
|
||||
{
|
||||
const double scale = 4096.0 / sizeof (Sample);
|
||||
|
||||
|
||||
if (_total_free_4k_blocks * scale > (double) max_frames) {
|
||||
return max_frames;
|
||||
}
|
||||
|
@ -3914,7 +3921,8 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
}
|
||||
|
||||
try {
|
||||
fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, buf, false, frame_rate()));
|
||||
fsource = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
@ -3931,7 +3939,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
to_do = len;
|
||||
|
||||
/* create a set of reasonably-sized buffers */
|
||||
buffers.ensure_buffers(nchans, chunk_size);
|
||||
buffers.ensure_buffers(nchans, chunk_size);
|
||||
buffers.set_count(nchans);
|
||||
|
||||
while (to_do && !itt.cancel) {
|
||||
|
|
|
@ -309,7 +309,6 @@ Session::second_stage_init (bool new_session)
|
|||
|
||||
if (!new_session) {
|
||||
if (load_state (_current_snapshot_name)) {
|
||||
cerr << "load state failed\n";
|
||||
return -1;
|
||||
}
|
||||
remove_empty_sounds ();
|
||||
|
@ -371,7 +370,6 @@ Session::second_stage_init (bool new_session)
|
|||
_end_location_is_free = false;
|
||||
}
|
||||
|
||||
restore_history(_current_snapshot_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -436,16 +434,7 @@ Session::setup_raid_path (string path)
|
|||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += sound_dir_name;
|
||||
fspath += ':';
|
||||
|
||||
/* tape dir */
|
||||
|
||||
fspath += sp.path;
|
||||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += tape_dir_name;
|
||||
fspath += sound_dir (false);
|
||||
|
||||
AudioFileSource::set_search_path (fspath);
|
||||
SMFSource::set_search_path (fspath); // FIXME: should be different
|
||||
|
@ -467,16 +456,7 @@ Session::setup_raid_path (string path)
|
|||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += sound_dir_name;
|
||||
fspath += ':';
|
||||
|
||||
/* add tape dir to file search path */
|
||||
|
||||
fspath += sp.path;
|
||||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += tape_dir_name;
|
||||
fspath += sound_dir (false);
|
||||
fspath += ':';
|
||||
|
||||
remaining = remaining.substr (colon+1);
|
||||
|
@ -492,15 +472,9 @@ Session::setup_raid_path (string path)
|
|||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += sound_dir_name;
|
||||
fspath += sound_dir (false);
|
||||
fspath += ':';
|
||||
|
||||
fspath += sp.path;
|
||||
if (fspath[fspath.length()-1] != '/') {
|
||||
fspath += '/';
|
||||
}
|
||||
fspath += tape_dir_name;
|
||||
|
||||
session_dirs.push_back (sp);
|
||||
}
|
||||
|
||||
|
@ -518,61 +492,40 @@ int
|
|||
Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
|
||||
{
|
||||
string dir;
|
||||
|
||||
new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
|
||||
|
||||
if (mkdir (_path.c_str(), 0755) < 0) {
|
||||
if (errno == EEXIST) {
|
||||
new_session = false;
|
||||
} else {
|
||||
error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
new_session = true;
|
||||
if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
|
||||
error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = peak_dir ();
|
||||
|
||||
if (mkdir (dir.c_str(), 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||
error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = sound_dir ();
|
||||
|
||||
if (mkdir (dir.c_str(), 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dir = tape_dir ();
|
||||
|
||||
if (mkdir (dir.c_str(), 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||
error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = dead_sound_dir ();
|
||||
|
||||
if (mkdir (dir.c_str(), 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||
error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = automation_dir ();
|
||||
|
||||
if (mkdir (dir.c_str(), 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -725,6 +678,8 @@ Session::save_state (string snapshot_name, bool pending)
|
|||
|
||||
}
|
||||
|
||||
cerr << "actually writing state\n";
|
||||
|
||||
if (!tree.write (xml_path)) {
|
||||
error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
|
||||
|
||||
|
@ -2031,13 +1986,12 @@ Session::load_sources (const XMLNode& node)
|
|||
boost::shared_ptr<Source>
|
||||
Session::XMLSourceFactory (const XMLNode& node)
|
||||
{
|
||||
|
||||
if (node.name() != "Source") {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
||||
try {
|
||||
return SourceFactory::create (node);
|
||||
return SourceFactory::create (*this, node);
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
@ -2062,7 +2016,7 @@ Session::save_template (string template_name)
|
|||
if ((dp = opendir (dir.c_str()))) {
|
||||
closedir (dp);
|
||||
} else {
|
||||
if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
|
||||
if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
|
||||
error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
@ -2142,11 +2096,9 @@ Session::ensure_sound_dir (string path, string& result)
|
|||
|
||||
/* Ensure that the parent directory exists */
|
||||
|
||||
if (mkdir (path.c_str(), 0775)) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (path.c_str(), 0775)) {
|
||||
error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ensure that the sounds directory exists */
|
||||
|
@ -2155,33 +2107,27 @@ Session::ensure_sound_dir (string path, string& result)
|
|||
result += '/';
|
||||
result += sound_dir_name;
|
||||
|
||||
if (mkdir (result.c_str(), 0775)) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (result.c_str(), 0775)) {
|
||||
error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dead = path;
|
||||
dead += '/';
|
||||
dead += dead_sound_dir_name;
|
||||
|
||||
if (mkdir (dead.c_str(), 0775)) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (dead.c_str(), 0775)) {
|
||||
error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
peak = path;
|
||||
peak += '/';
|
||||
peak += peak_dir_name;
|
||||
|
||||
if (mkdir (peak.c_str(), 0775)) {
|
||||
if (errno != EEXIST) {
|
||||
error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
if (g_mkdir_with_parents (peak.c_str(), 0775)) {
|
||||
error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* callers expect this to be terminated ... */
|
||||
|
@ -2196,12 +2142,6 @@ Session::discover_best_sound_dir (bool destructive)
|
|||
vector<space_and_path>::iterator i;
|
||||
string result;
|
||||
|
||||
/* destructive files all go into the same place */
|
||||
|
||||
if (destructive) {
|
||||
return tape_dir();
|
||||
}
|
||||
|
||||
/* handle common case without system calls */
|
||||
|
||||
if (session_dirs.size() == 1) {
|
||||
|
@ -2418,20 +2358,37 @@ Session::dead_sound_dir () const
|
|||
}
|
||||
|
||||
string
|
||||
Session::sound_dir () const
|
||||
Session::sound_dir (bool with_path) const
|
||||
{
|
||||
string res = _path;
|
||||
/* support old session structure */
|
||||
|
||||
struct stat statbuf;
|
||||
string old;
|
||||
|
||||
if (with_path) {
|
||||
old = _path;
|
||||
}
|
||||
|
||||
old += sound_dir_name;
|
||||
old += '/';
|
||||
|
||||
if (stat (old.c_str(), &statbuf) == 0) {
|
||||
return old;
|
||||
}
|
||||
|
||||
string res;
|
||||
|
||||
if (with_path) {
|
||||
res = _path;
|
||||
}
|
||||
|
||||
res += interchange_dir_name;
|
||||
res += '/';
|
||||
res += legalize_for_path (_name);
|
||||
res += '/';
|
||||
res += sound_dir_name;
|
||||
res += '/';
|
||||
return res;
|
||||
}
|
||||
|
||||
string
|
||||
Session::tape_dir () const
|
||||
{
|
||||
string res = _path;
|
||||
res += tape_dir_name;
|
||||
res += '/';
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -3427,8 +3384,7 @@ Session::save_history (string snapshot_name)
|
|||
XMLTree tree;
|
||||
string xml_path;
|
||||
string bak_path;
|
||||
|
||||
|
||||
|
||||
tree.set_root (&history.get_state());
|
||||
|
||||
if (snapshot_name.empty()) {
|
||||
|
@ -3436,7 +3392,6 @@ Session::save_history (string snapshot_name)
|
|||
}
|
||||
|
||||
xml_path = _path + snapshot_name + ".history";
|
||||
cerr << "Saving history to " << xml_path << endmsg;
|
||||
|
||||
bak_path = xml_path + ".bak";
|
||||
|
||||
|
@ -3447,6 +3402,8 @@ Session::save_history (string snapshot_name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
cerr << "actually writing history\n";
|
||||
|
||||
if (!tree.write (xml_path))
|
||||
{
|
||||
error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
|
||||
|
|
|
@ -51,7 +51,7 @@ Session::bbt_time (jack_nframes_t when, BBT_Time& bbt)
|
|||
void
|
||||
Session::sync_time_vars ()
|
||||
{
|
||||
_current_frame_rate = _base_frame_rate * (1.0 + (video_pullup/100.0) );
|
||||
_current_frame_rate = (jack_nframes_t) round (_base_frame_rate * (1.0 + (video_pullup/100.0)));
|
||||
_frames_per_hour = _current_frame_rate * 3600;
|
||||
_frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
|
||||
_smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
|
||||
|
@ -432,9 +432,11 @@ Session::jack_timebase_callback (jack_transport_state_t state,
|
|||
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
|
||||
}
|
||||
|
||||
#ifdef HAVE_JACK_VIDEO_SUPPORT
|
||||
//poke audio video ratio so Ardour can track Video Sync
|
||||
pos->audio_frames_per_video_frame = frame_rate() / smpte_frames_per_second;
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* SMPTE info */
|
||||
|
|
|
@ -82,8 +82,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
|
|||
}
|
||||
|
||||
try {
|
||||
sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, path, false, frame_rate())));
|
||||
sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *this, path, false, frame_rate())));
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
|
||||
|
|
|
@ -48,8 +48,8 @@ bool SMFSource::header_position_negative;
|
|||
uint64_t SMFSource::header_position_offset;
|
||||
*/
|
||||
|
||||
SMFSource::SMFSource (std::string path, Flag flags)
|
||||
: MidiSource (region_name_from_path(path))
|
||||
SMFSource::SMFSource (Session& s, std::string path, Flag flags)
|
||||
: MidiSource (s, region_name_from_path(path))
|
||||
, _channel(0)
|
||||
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
|
||||
, _allow_remove_if_empty(true)
|
||||
|
@ -72,8 +72,8 @@ SMFSource::SMFSource (std::string path, Flag flags)
|
|||
assert(_name.find("/") == string::npos);
|
||||
}
|
||||
|
||||
SMFSource::SMFSource (const XMLNode& node)
|
||||
: MidiSource (node)
|
||||
SMFSource::SMFSource (Session& s, const XMLNode& node)
|
||||
: MidiSource (s, node)
|
||||
, _channel(0)
|
||||
, _flags (Flag (Writable|CanRename))
|
||||
, _allow_remove_if_empty(true)
|
||||
|
|
|
@ -34,8 +34,8 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
SndFileSource::SndFileSource (const XMLNode& node)
|
||||
: AudioFileSource (node)
|
||||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
|
||||
|
@ -52,9 +52,9 @@ SndFileSource::SndFileSource (const XMLNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (string idstr, Flag flags)
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
{
|
||||
init (idstr);
|
||||
|
||||
|
@ -71,8 +71,8 @@ SndFileSource::SndFileSource (string idstr, Flag flags)
|
|||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
|
||||
: AudioFileSource(idstr, flags, sfmt, hf)
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, idstr, flags, sfmt, hf)
|
||||
{
|
||||
int fmt = 0;
|
||||
|
||||
|
@ -226,7 +226,6 @@ SndFileSource::open ()
|
|||
|
||||
_length = _info.frames;
|
||||
|
||||
|
||||
_broadcast_info = new SF_BROADCAST_INFO;
|
||||
memset (_broadcast_info, 0, sizeof (*_broadcast_info));
|
||||
|
||||
|
@ -507,6 +506,9 @@ SndFileSource::set_header_timeline_position ()
|
|||
delete _broadcast_info;
|
||||
_broadcast_info = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
|
|
|
@ -42,11 +42,9 @@ using std::max;
|
|||
|
||||
using namespace ARDOUR;
|
||||
|
||||
sigc::signal<void,Source*> Source::SourceCreated;
|
||||
|
||||
|
||||
Source::Source (string name, DataType type)
|
||||
: _type(type)
|
||||
Source::Source (Session& s, string name, DataType type)
|
||||
: _session (s)
|
||||
, _type(type)
|
||||
{
|
||||
assert(_name.find("/") == string::npos);
|
||||
|
||||
|
@ -55,8 +53,9 @@ Source::Source (string name, DataType type)
|
|||
_length = 0;
|
||||
}
|
||||
|
||||
Source::Source (const XMLNode& node)
|
||||
: _type(DataType::AUDIO)
|
||||
Source::Source (Session& s, const XMLNode& node)
|
||||
: _session (s)
|
||||
, _type(DataType::AUDIO)
|
||||
{
|
||||
_timestamp = 0;
|
||||
_length = 0;
|
||||
|
|
|
@ -37,7 +37,7 @@ sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
|
|||
|
||||
#ifdef HAVE_COREAUDIO
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::create (const XMLNode& node)
|
||||
SourceFactory::create (Session& s, const XMLNode& node)
|
||||
{
|
||||
DataType type = DataType::AUDIO;
|
||||
const XMLProperty* prop = node.property("type");
|
||||
|
@ -49,11 +49,18 @@ SourceFactory::create (const XMLNode& node)
|
|||
|
||||
if (node.property (X_("destructive")) != 0) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (node));
|
||||
|
@ -83,7 +90,7 @@ SourceFactory::create (const XMLNode& node)
|
|||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::create (const XMLNode& node)
|
||||
SourceFactory::create (Session& s, const XMLNode& node)
|
||||
{
|
||||
DataType type = DataType::AUDIO;
|
||||
const XMLProperty* prop = node.property("type");
|
||||
|
@ -95,20 +102,20 @@ SourceFactory::create (const XMLNode& node)
|
|||
|
||||
if (node.property (X_("destructive")) != 0) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (node));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (node));
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
|
@ -121,35 +128,34 @@ SourceFactory::create (const XMLNode& node)
|
|||
|
||||
#ifdef HAVE_COREAUDIO
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
if (flags & Destructive) {
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (node));
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
|
@ -161,10 +167,11 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
|
|||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
|
@ -172,8 +179,10 @@ SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Fla
|
|||
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (idstr, SMFSource::Flag(0))); // FIXME: flags?
|
||||
SourceCreated (ret);
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, idstr, SMFSource::Flag(0))); // FIXME: flags?
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -184,13 +193,14 @@ SourceFactory::createReadable (DataType type, string idstr, AudioFileSource::Fla
|
|||
#endif // HAVE_COREAUDIO
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createWritable (DataType type, std::string path, bool destructive, jack_nframes_t rate, bool announce)
|
||||
SourceFactory::createWritable (DataType type, Session& s, std::string path, bool destructive, jack_nframes_t rate, bool announce)
|
||||
{
|
||||
/* this might throw failed_constructor(), which is OK */
|
||||
|
||||
if (type == DataType::AUDIO) {
|
||||
if (destructive) {
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (path,
|
||||
|
||||
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, path,
|
||||
Config->get_native_file_data_format(),
|
||||
Config->get_native_file_header_format(),
|
||||
rate));
|
||||
|
@ -200,7 +210,8 @@ SourceFactory::createWritable (DataType type, std::string path, bool destructive
|
|||
return ret;
|
||||
|
||||
} else {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (path,
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path,
|
||||
Config->get_native_file_data_format(),
|
||||
Config->get_native_file_header_format(),
|
||||
rate));
|
||||
|
@ -208,13 +219,15 @@ SourceFactory::createWritable (DataType type, std::string path, bool destructive
|
|||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (path));
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, path));
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source> ();
|
||||
|
|
|
@ -919,6 +919,33 @@ jack_nframes_t
|
|||
|
||||
TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
|
||||
{
|
||||
|
||||
BBT_Time the_beat;
|
||||
uint32_t ticks_one_half_subdivisions_worth;
|
||||
uint32_t ticks_one_subdivisions_worth;
|
||||
|
||||
bbt_time(fr, the_beat);
|
||||
|
||||
ticks_one_subdivisions_worth = (uint32_t)Meter::ticks_per_beat / sub_num;
|
||||
ticks_one_half_subdivisions_worth = ticks_one_subdivisions_worth / 2;
|
||||
|
||||
if (the_beat.ticks % ticks_one_subdivisions_worth > ticks_one_half_subdivisions_worth) {
|
||||
uint32_t difference = ticks_one_subdivisions_worth - (the_beat.ticks % ticks_one_subdivisions_worth);
|
||||
if (the_beat.ticks + difference >= (uint32_t)Meter::ticks_per_beat) {
|
||||
the_beat.beats++;
|
||||
the_beat.ticks += difference;
|
||||
the_beat.ticks -= (uint32_t)Meter::ticks_per_beat;
|
||||
} else {
|
||||
the_beat.ticks += difference;
|
||||
}
|
||||
} else {
|
||||
the_beat.ticks -= the_beat.ticks % ticks_one_subdivisions_worth;
|
||||
}
|
||||
|
||||
return frame_time (the_beat);
|
||||
|
||||
/* XXX just keeping this for reference
|
||||
|
||||
TempoMap::BBTPointList::iterator i;
|
||||
TempoMap::BBTPointList *more_zoomed_bbt_points;
|
||||
jack_nframes_t frame_one_beats_worth;
|
||||
|
@ -970,6 +997,9 @@ TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
|
|||
|
||||
delete more_zoomed_bbt_points;
|
||||
return fr ;
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
|
|
|
@ -287,7 +287,7 @@ compute_equal_power_fades (jack_nframes_t nframes, float* in, float* out)
|
|||
|
||||
in[0] = 0.0f;
|
||||
|
||||
for (int i = 1; i < nframes - 1; ++i) {
|
||||
for (jack_nframes_t i = 1; i < nframes - 1; ++i) {
|
||||
in[i] = in[i-1] + step;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,9 +174,9 @@ VSTPlugin::get_state()
|
|||
|
||||
if (stat (path.c_str(), &sbuf)) {
|
||||
if (errno == ENOENT) {
|
||||
if (mkdir (path.c_str(), 0600)) {
|
||||
if (g_mkdir_with_parents (path.c_str(), 0600)) {
|
||||
error << string_compose (_("cannot create VST chunk directory: %1"),
|
||||
strerror (errno))
|
||||
strerror (errno))
|
||||
<< endmsg;
|
||||
return *root;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
|
|||
uint32_t cnt = selection->size();
|
||||
uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
|
||||
|
||||
cerr << "lets plan to serialize " << cnt << " from selection\n";
|
||||
|
||||
char* buf = new char[sz];
|
||||
SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
|
||||
|
||||
|
@ -59,10 +61,12 @@ DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHan
|
|||
cnt = 0;
|
||||
|
||||
for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
|
||||
cerr << "getting next item\n";
|
||||
TreeModel::Row row = *(model->get_iter (*x));
|
||||
row.get_value (data_column, sr->ptr[cnt]);
|
||||
}
|
||||
|
||||
|
||||
cerr << "returning an SR with size = " << sr->size << endl;
|
||||
return sr;
|
||||
}
|
||||
|
||||
|
@ -79,6 +83,7 @@ DnDTreeView::on_drag_data_get(const RefPtr<DragContext>& context, SelectionData&
|
|||
SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
|
||||
selection_data.set (8, (guchar*)sr, sr->size);
|
||||
|
||||
cerr << "selection data set to contain " << sr->size << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class Stateful {
|
|||
|
||||
virtual void add_instant_xml (XMLNode&, const std::string& dir);
|
||||
XMLNode *instant_xml (const std::string& str, const std::string& dir);
|
||||
PBD::ID id() { return _id; }
|
||||
const PBD::ID& id() const { return _id; }
|
||||
|
||||
protected:
|
||||
XMLNode *_extra_xml;
|
||||
|
|
Loading…
Reference in New Issue