fade_in_active_changed ();
fade_out_active_changed ();
+ reset_width_dependent_items (_pixel_width);
+
fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if ((*i)->crossfade == crossfade) {
+
if (!crossfades_visible || layer_display == Stacked) {
(*i)->hide();
} else {
_samples_per_unit,
region_color,
*lview, *rview);
-
+ cv->set_valid (true);
crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
crossfade_views.push_back (cv);
-
if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) {
cv->hide ();
}
apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
}
+ RegionViewList copy;
+
for (i = region_views.begin(); i != region_views.end(); ) {
tmp = i;
tmp++;
if (!(*i)->is_valid()) {
delete *i;
region_views.erase (i);
+ i = tmp;
+ continue;
} else {
(*i)->enable_display(true);
}
+ /*
+ sort regionviews by layer so that when we call region_layered ()
+ the canvas layering works out (in non-stacked mode).
+ */
+
+ if (copy.size() == 0) {
+ copy.push_front((*i));
+ i = tmp;
+ continue;
+ }
+
+ RegionViewList::iterator k = copy.begin();
+ RegionViewList::iterator l = copy.end();
+ l--;
+
+ if ((*i)->region()->layer() <= (*k)->region()->layer()) {
+ copy.push_front((*i));
+ i = tmp;
+ continue;
+ } else if ((*i)->region()->layer() >= (*l)->region()->layer()) {
+ copy.push_back((*i));
+ i = tmp;
+ continue;
+ }
+
+ for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) {
+
+ if ((*j)->region()->layer() >= (*i)->region()->layer()) {
+ copy.insert(j, (*i));
+ break;
+ }
+ }
+
i = tmp;
+
}
for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
xi = tmpx;
}
- /* now fix layering */
-
- for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
- region_layered (*i);
+ /* now fix canvas layering */
+
+ for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) {
+ (*j)->enable_display(true);
+ (*j)->set_y_position_and_height(0, height);
+ region_layered (*j);
}
}
range_marker_drag_rect = 0;
marker_drag_line = 0;
-
+ tempo_map_change_idle_handler_id = -1;
+ canvas_hroizontally_scrolled_handler_id = -1;
set_midi_edit_mode (MidiEditPencil, true);
set_mouse_mode (MouseObject, true);
case SnapToAEighthBeat:
case SnapToAQuarterBeat:
case SnapToAThirdBeat:
+ compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
update_tempo_based_rulers ();
+ break;
default:
/* relax */
break;
/* Zoom */
zoom_box.set_spacing (1);
- zoom_box.set_border_width (2);
+ zoom_box.set_border_width (0);
zoom_in_button.set_name ("EditorTimeButton");
zoom_in_button.set_size_request(-1,16);
frames_per_unit = fpu;
- if (frames != zoom_range_clock.current_duration()) {
- zoom_range_clock.set (frames);
- }
-
if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
if (!selection->tracks.empty()) {
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
pending_visual_change.frames_per_unit = fpu;
if (pending_visual_change.idle_handler_id < 0) {
- pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, _idle_visual_changer, this, 0);
+ pending_visual_change.idle_handler_id = g_idle_add ( _idle_visual_changer, this);
}
+
}
int
VisualChange::Type p = pending_visual_change.pending;
pending_visual_change.pending = (VisualChange::Type) 0;
- pending_visual_change.idle_handler_id = -1;
if (p & VisualChange::ZoomLevel) {
set_frames_per_unit (pending_visual_change.frames_per_unit);
- }
+ compute_fixed_ruler_scale ();
+ compute_current_bbt_points(pending_visual_change.time_origin, pending_visual_change.time_origin + (nframes_t)(canvas_width * pending_visual_change.frames_per_unit));
+ compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + (nframes_t)(canvas_width * pending_visual_change.frames_per_unit));
+ update_tempo_based_rulers ();
+ }
if (p & VisualChange::TimeOrigin) {
if (pending_visual_change.time_origin != leftmost_frame) {
horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
redisplay_tempo (true);
}
}
+ pending_visual_change.idle_handler_id = -1;
return 0; /* this is always a one-shot call */
}
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
void collect_new_region_view (RegionView *);
+ void collect_and_select_new_region_view (RegionView *);
Gtk::MenuItem* region_edit_menu_split_item;
Gtk::MenuItem* region_edit_menu_split_multichannel_item;
void initialize_rulers ();
void update_just_smpte ();
+ void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
void update_fixed_rulers ();
void update_tempo_based_rulers ();
void popup_ruler_menu (nframes_t where = 0, ItemType type = RegionItem);
static gint _metric_get_frames (GtkCustomRulerMark **, gdouble, gdouble, gint);
static gint _metric_get_minsec (GtkCustomRulerMark **, gdouble, gdouble, gint);
+ enum MinsecRulerScale {
+ minsec_show_seconds,
+ minsec_show_minutes,
+ minsec_show_hours,
+ minsec_show_frames
+ };
+
+ MinsecRulerScale minsec_ruler_scale;
+
+ nframes_t minsec_mark_interval;
+ gint minsec_mark_modulo;
+ gint minsec_nmarks;
+ void set_minsec_ruler_scale (gdouble lower, gdouble upper);
+
+ enum SMPTERulerScale {
+ smpte_show_bits,
+ smpte_show_frames,
+ smpte_show_seconds,
+ smpte_show_minutes,
+ smpte_show_hours
+ };
+
+ SMPTERulerScale smpte_ruler_scale;
+
+ nframes_t smpte_mark_interval;
+ gint smpte_mark_modulo;
+ gint smpte_nmarks;
+ void set_smpte_ruler_scale (gdouble lower, gdouble upper);
+
+ enum BBTRulerScale {
+ bbt_over,
+ bbt_show_64,
+ bbt_show_16,
+ bbt_show_4,
+ bbt_show_1,
+ bbt_show_beats,
+ bbt_show_ticks,
+ bbt_show_ticks_detail,
+ bbt_show_ticks_super_detail
+ };
+
+ BBTRulerScale bbt_ruler_scale;
+
+ uint32_t bbt_bars;
+ gint bbt_nmarks;
+ uint32_t bbt_bar_helper_on;
+ uint32_t bbt_accent_modulo;
+ void compute_bbt_ruler_scale (nframes_t lower, nframes_t upper);
+
gint metric_get_smpte (GtkCustomRulerMark **, gdouble, gdouble, gint);
gint metric_get_bbt (GtkCustomRulerMark **, gdouble, gdouble, gint);
gint metric_get_frames (GtkCustomRulerMark **, gdouble, gdouble, gint);
void tie_vertical_scrolling ();
void canvas_horizontally_scrolled ();
+ static int _idle_canvas_horizontally_scrolled (void *arg);
+ bool idle_canvas_horizontally_scrolled ();
struct VisualChange {
enum Type {
void handle_new_duration ();
void initialize_canvas ();
+ int canvas_hroizontally_scrolled_handler_id;
+ void reset_horizontally_scrolling_region (Gtk::Allocation* alloc = 0);
void reset_scrolling_region (Gtk::Allocation* alloc = 0);
/* display control */
void remove_metric_marks ();
void draw_metric_marks (const ARDOUR::Metrics& metrics);
+ void compute_current_bbt_points (nframes_t left, nframes_t right);
+ int tempo_map_change_idle_handler_id;
void tempo_map_changed (ARDOUR::Change);
void redisplay_tempo (bool immediate_redraw);
transport_punchout_line->property_y1() = 0.0;
transport_punchout_line->property_y2() = canvas_height;
}
-
+ compute_fixed_ruler_scale ();
update_fixed_rulers();
redisplay_tempo (true);
if (session) {
if (export_dialog == 0) {
export_dialog = new ExportSessionDialog (*this);
+ export_dialog->connect_to_session (session);
}
- export_dialog->connect_to_session (session);
export_dialog->set_range (start, end);
export_dialog->start_export();
}
if (export_range_markers_dialog == 0) {
export_range_markers_dialog = new ExportRangeMarkersDialog(*this);
+ export_range_markers_dialog->connect_to_session (session);
}
-
- export_range_markers_dialog->connect_to_session (session);
+
export_range_markers_dialog->start_export();
}
}
vector<RegionView*> new_regionviews;
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+
RegionView* rv;
RegionView* nrv;
}
/* reset selection to new regionviews */
-
+
selection->set (new_regionviews);
/* reset drag_info data to reflect the fact that we are dragging the copies */
tvp2 = trackview_by_y_position (iy1 + y_delta);
temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
rv->set_y_position_and_height (0, temp_rtv->height);
-
+
/* if you un-comment the following, the region colours will follow the track colours whilst dragging,
personally, i think this can confuse things, but never mind.
*/
Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
nframes_t where;
- RegionView* rv = reinterpret_cast<RegionView *> (drag_info.data);
+ RegionView* rvdi = reinterpret_cast<RegionView *> (drag_info.data);
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
bool nocommit = true;
double speed;
bool regionview_y_movement;
bool regionview_x_movement;
vector<RegionView*> copies;
+ list <boost::shared_ptr<Playlist > > used_playlists;
+ list <sigc::connection > used_connections;
+ bool preserve_selection = false;
/* first_move is set to false if the regionview has been moved in the
motion handler.
speed = rtv->get_diskstream()->speed();
}
- regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed));
- regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
+ regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rvdi->region()->position()/speed));
+ regionview_y_movement = (drag_info.last_trackview != &rvdi->get_time_axis_view());
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
/* moved to a different audio track. */
- vector<RegionView*> new_selection;
-
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
- RegionView* rv = (*i);
+ RegionView* rv = (*i);
double ix1, ix2, iy1, iy2;
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
rv->get_canvas_group()->i2w (ix1, iy1);
- TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
- boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
+ RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(trackview_by_y_position (iy1));
+
boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
+ if (! to_playlist->frozen()) {
+ /*
+ we haven't seen this playlist before.
+ we want to freeze it because we don't want to relayer per-region.
+ its much better to do that just once if the playlist is large.
+ */
+
+ /*
+ connect so the selection is changed when the new regionview finally appears (after thaw).
+ keep track of it so we can disconnect later.
+ */
+
+ sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+ used_connections.push_back (c);
+
+ /* undo */
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+
+ /* remember used playlists so we can thaw them later */
+ used_playlists.push_back(to_playlist);
+ to_playlist->freeze();
+ }
+
where = (nframes_t) (unit_to_frame (ix1) * speed);
boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
- /* undo the previous hide_dependent_views so that xfades don't
- disappear on copying regions
- */
+ if (!drag_info.copy) {
- rv->get_time_axis_view().reveal_dependent_views (*rv);
- if (!drag_info.copy) {
-
/* the region that used to be in the old playlist is not
moved to the new one - we make a copy of it. as a result,
any existing editor for the region should no longer be
visible.
*/
-
+
+ RouteTimeAxisView* from_playlist_rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_trackview());
+ boost::shared_ptr<Playlist> from_playlist = from_playlist_rtv->playlist();
+
+ if (! from_playlist->frozen()) {
+ from_playlist->freeze();
+ used_playlists.push_back(from_playlist);
+
+ sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+ used_connections.push_back (c);
+
+ session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
+ }
+
rv->hide_region_editor();
rv->fake_set_opaque (false);
- session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
from_playlist->remove_region ((rv->region()));
- session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
} else {
/* the regionview we dragged around is a temporary copy, queue it for deletion */
-
+
copies.push_back (rv);
}
latest_regionview = 0;
-
- sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
- session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+
to_playlist->add_region (new_region, where);
- session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
- c.disconnect ();
-
- if (latest_regionview) {
- new_selection.push_back (latest_regionview);
- }
/* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
was selected in all of them, then removing it from the playlist will have removed all
EXCEPT .... if we are doing a copy drag, then the selection hasn't been modified and
we can just iterate.
+
*/
if (drag_info.copy) {
if (selection->regions.empty()) {
break;
} else {
- i = selection->regions.by_layer().begin();
+ /*
+ XXX see above .. but we just froze the playlists.. we have to keep iterating, right?
+ */
+
+ //i = selection->regions.by_layer().begin();
+ ++i;
}
}
- }
-
- selection->set (new_selection);
+ }
} else {
list<RegionView*> regions = selection->regions.by_layer();
- if (drag_info.copy) {
- selection->clear_regions();
- }
-
for (list<RegionView*>::iterator i = regions.begin(); i != regions.end(); ++i) {
- rv = (*i);
+ RegionView* rv = (*i);
+ boost::shared_ptr<Playlist> to_playlist = (*i)->region()->playlist();
+ RouteTimeAxisView* from_rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
if (!rv->region()->can_move()) {
continue;
if (regionview_x_movement) {
double ownspeed = 1.0;
- rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
- if (rtv && rtv->get_diskstream()) {
- ownspeed = rtv->get_diskstream()->speed();
+ if (from_rtv && from_rtv->get_diskstream()) {
+ ownspeed = from_rtv->get_diskstream()->speed();
}
/* base the new region position on the current position of the regionview.*/
where = rv->region()->position();
}
- boost::shared_ptr<Playlist> to_playlist = rv->region()->playlist();
+ if (! to_playlist->frozen()) {
+ sigc::connection c = from_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+ used_connections.push_back (c);
- assert (to_playlist);
+ /* add the undo */
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
- /* add the undo */
-
- session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+ used_playlists.push_back(to_playlist);
+ to_playlist->freeze();
+ }
if (drag_info.copy) {
/* add it */
- latest_regionview = 0;
- sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
- to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
- c.disconnect ();
-
- if (latest_regionview) {
- rtv->reveal_dependent_views (*latest_regionview);
- selection->add (latest_regionview);
- }
+ to_playlist->add_region (newregion, (nframes_t) (where * from_rtv->get_diskstream()->speed()));
/* if the original region was locked, we don't care for the new one */
- newregion->set_locked (false);
+ newregion->set_locked (false);
+ copies.push_back (rv);
} else {
/* just change the model */
rv->region()->set_position (where, (void*) this);
+ preserve_selection = true;
}
- /* add the redo */
+ }
- session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
+ }
+ if (! preserve_selection) {
+ //selection->clear_regions();
+ }
+ while (used_playlists.size() > 0) {
- if (drag_info.copy) {
- copies.push_back (rv);
- }
+ list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
+ (*i)->thaw();
+
+ if (used_connections.size()) {
+ sigc::connection c = used_connections.front();
+ c.disconnect();
+ used_connections.pop_front();
}
+ /* add the redo */
+
+ session->add_command (new MementoCommand<Playlist>(*(*i), 0, &(*i)->get_state()));
+ used_playlists.pop_front();
}
out:
latest_regionview = rv;
}
+void
+Editor::collect_and_select_new_region_view (RegionView* rv)
+{
+ selection->add(rv);
+ latest_regionview = rv;
+}
+
void
Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
/* we need to deselect all other regionviews, and select this one
i'm ignoring undo stuff, because the region creation will take care of it */
- selection->set (latest_regionview);
+ //selection->set (latest_regionview);
drag_info.item = latest_regionview->get_canvas_group();
drag_info.data = latest_regionview;
insert_result = motion_frozen_playlists.insert (pl);
if (insert_result.second) {
session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
+ pl->freeze();
}
}
}
}
for (set<boost::shared_ptr<Playlist> >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
- //(*p)->thaw ();
+ (*p)->thaw ();
session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
}
void
Editor::split_regions_at (nframes_t where, RegionSelection& regions)
{
+ list <boost::shared_ptr<Playlist > > used_playlists;
+
begin_reversible_command (_("split"));
// if splitting a single region, and snap-to is using
snap_to (where);
}
- for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
- RegionSelection::iterator tmp;
-
- tmp = a;
- ++tmp;
+ for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ++a) {
boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
+ if (! pl->frozen()) {
+ /* we haven't seen this playlist before */
+
+ /* remember used playlists so we can thaw them later */
+ used_playlists.push_back(pl);
+ pl->freeze();
+ }
+
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
if (arv)
_new_regionviews_show_envelope = arv->envelope_visible();
session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
}
- a = tmp;
- }
+ }
+ while (used_playlists.size() > 0) {
+ list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
+ (*i)->thaw();
+ used_playlists.pop_front();
+ }
commit_reversible_command ();
_new_regionviews_show_envelope = false;
}
time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
time_canvas_event_box.queue_resize();
-
+ compute_fixed_ruler_scale();
update_fixed_rulers();
- //update_tempo_based_rulers();
- redisplay_tempo (false);
time_canvas_event_box.show_all();
time_button_frame.show_all();
+
+ compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
+ compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
+
+ redisplay_tempo (false);
}
void
}
}
+void
+Editor::compute_fixed_ruler_scale ()
+{
+ if (session == 0) {
+ return;
+ }
+
+ if (ruler_shown[ruler_metric_smpte]) {
+ set_smpte_ruler_scale (leftmost_frame, leftmost_frame + (canvas_width * frames_per_unit) );
+ }
+
+ if (ruler_shown[ruler_metric_minsec]) {
+ set_minsec_ruler_scale (leftmost_frame, leftmost_frame + (canvas_width * frames_per_unit) );
+ }
+}
+
void
Editor::update_fixed_rulers ()
{
}
ruler_metrics[ruler_metric_bbt].units_per_pixel = frames_per_unit;
-
+
if (ruler_shown[ruler_metric_bbt]) {
gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_bbt_ruler), leftmost_frame, leftmost_frame+current_page_frames(),
leftmost_frame, session->current_end_frame());
return ruler_editor->metric_get_minsec (marks, lower, upper, maxchars);
}
-gint
-Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper)
{
nframes_t range;
- nframes_t pos;
nframes_t spacer;
nframes_t fr;
- SMPTE::Time smpte;
- gchar buf[16];
- gint nmarks = 0;
- gint n;
- bool show_bits = false;
- bool show_frames = false;
- bool show_seconds = false;
- bool show_minutes = false;
- bool show_hours = false;
- int mark_modulo;
if (session == 0) {
- return 0;
+ return;
}
fr = session->frame_rate();
range = (nframes_t) floor (upper - lower);
if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
- show_bits = true;
- mark_modulo = 20;
- nmarks = 1 + (2 * Config->get_subframes_per_frame());
+ smpte_ruler_scale = smpte_show_bits;
+ smpte_mark_modulo = 20;
+ smpte_nmarks = 2 + (2 * Config->get_subframes_per_frame());
} else if (range <= (fr / 4)) { /* 2 frames - 0.250 second */
- show_frames = true;
- mark_modulo = 1;
- nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+ smpte_ruler_scale = smpte_show_frames;
+ smpte_mark_modulo = 1;
+ smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
} else if (range <= (fr / 2)) { /* 0.25-0.5 second */
- show_frames = true;
- mark_modulo = 2;
- nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+ smpte_ruler_scale = smpte_show_frames;
+ smpte_mark_modulo = 2;
+ smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
} else if (range <= fr) { /* 0.5-1 second */
- show_frames = true;
- mark_modulo = 5;
- nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+ smpte_ruler_scale = smpte_show_frames;
+ smpte_mark_modulo = 5;
+ smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
} else if (range <= 2 * fr) { /* 1-2 seconds */
- show_frames = true;
- mark_modulo = 10;
- nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+ smpte_ruler_scale = smpte_show_frames;
+ smpte_mark_modulo = 10;
+ smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
} else if (range <= 8 * fr) { /* 2-8 seconds */
- show_seconds = true;
- mark_modulo = 1;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 1;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 16 * fr) { /* 8-16 seconds */
- show_seconds = true;
- mark_modulo = 2;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 2;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 30 * fr) { /* 16-30 seconds */
- show_seconds = true;
- mark_modulo = 5;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 5;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 60 * fr) { /* 30-60 seconds */
- show_seconds = true;
- mark_modulo = 5;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 5;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
- show_seconds = true;
- mark_modulo = 20;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 15;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 4 * 60 * fr) { /* 2-4 minutes */
- show_seconds = true;
- mark_modulo = 30;
- nmarks = 1 + (range / fr);
+ smpte_ruler_scale = smpte_show_seconds;
+ smpte_mark_modulo = 30;
+ smpte_nmarks = 2 + (range / fr);
} else if (range <= 10 * 60 * fr) { /* 4-10 minutes */
- show_minutes = true;
- mark_modulo = 2;
- nmarks = 1 + 10;
+ smpte_ruler_scale = smpte_show_minutes;
+ smpte_mark_modulo = 2;
+ smpte_nmarks = 2 + 10;
} else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
- show_minutes = true;
- mark_modulo = 5;
- nmarks = 1 + 30;
+ smpte_ruler_scale = smpte_show_minutes;
+ smpte_mark_modulo = 5;
+ smpte_nmarks = 2 + 30;
} else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
- show_minutes = true;
- mark_modulo = 10;
- nmarks = 1 + 60;
+ smpte_ruler_scale = smpte_show_minutes;
+ smpte_mark_modulo = 10;
+ smpte_nmarks = 2 + 60;
} else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
- show_minutes = true;
- mark_modulo = 30;
- nmarks = 1 + (60 * 4);
+ smpte_ruler_scale = smpte_show_minutes;
+ smpte_mark_modulo = 30;
+ smpte_nmarks = 2 + (60 * 4);
} else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
- show_hours = true;
- mark_modulo = 1;
- nmarks = 1 + 8;
+ smpte_ruler_scale = smpte_show_hours;
+ smpte_mark_modulo = 1;
+ smpte_nmarks = 2 + 8;
} else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
- show_hours = true;
- mark_modulo = 1;
- nmarks = 1 + 24;
+ smpte_ruler_scale = smpte_show_hours;
+ smpte_mark_modulo = 1;
+ smpte_nmarks = 2 + 24;
} else {
/* not possible if nframes_t is a 32 bit quantity */
- show_hours = true;
- mark_modulo = 4;
- nmarks = 1 + 24;
+ smpte_ruler_scale = smpte_show_hours;
+ smpte_mark_modulo = 4;
+ smpte_nmarks = 2 + 24;
}
+}
+
+gint
+Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+ nframes_t pos;
+ nframes_t spacer;
+ SMPTE::Time smpte;
+ gchar buf[16];
+ gint n;
+
+ if (session == 0) {
+ return 0;
+ }
+
+ if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
+ lower = lower - spacer;
+ } else {
+ lower = 0;
+ }
+
pos = (nframes_t) floor (lower);
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-
- if (show_bits) {
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * smpte_nmarks);
+ switch (smpte_ruler_scale) {
+ case smpte_show_bits:
+
// Find smpte time of this sample (pos) with subframe accuracy
session->sample_to_smpte(pos, smpte, true /* use_offset */, true /* use_subframes */ );
- for (n = 0; n < nmarks; n++) {
+ for (n = 0; n < smpte_nmarks; n++) {
session->smpte_to_sample(smpte, pos, true /* use_offset */, true /* use_subframes */ );
- if ((smpte.subframes % mark_modulo) == 0) {
+ if ((smpte.subframes % smpte_mark_modulo) == 0) {
if (smpte.subframes == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
// Increment subframes by one
SMPTE::increment_subframes( smpte );
}
- } else if (show_seconds) {
+ break;
+ case smpte_show_seconds:
// Find smpte time of this sample (pos)
session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
// Go to next whole second down
SMPTE::seconds_floor( smpte );
- for (n = 0; n < nmarks; n++) {
+ for (n = 0; n < smpte_nmarks; n++) {
session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
- if ((smpte.seconds % mark_modulo) == 0) {
+ if ((smpte.seconds % smpte_mark_modulo) == 0) {
if (smpte.seconds == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
(*marks)[n].position = pos;
(*marks)[n].label = g_strdup (buf);
SMPTE::increment_seconds( smpte );
}
- } else if (show_minutes) {
+ break;
+ case smpte_show_minutes:
// Find smpte time of this sample (pos)
session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
// Go to next whole minute down
SMPTE::minutes_floor( smpte );
- for (n = 0; n < nmarks; n++) {
+ for (n = 0; n < smpte_nmarks; n++) {
session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
- if ((smpte.minutes % mark_modulo) == 0) {
+ if ((smpte.minutes % smpte_mark_modulo) == 0) {
if (smpte.minutes == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
} else {
(*marks)[n].position = pos;
SMPTE::increment_minutes( smpte );
}
- } else if (show_hours) {
+
+ break;
+ case smpte_show_hours:
// Find smpte time of this sample (pos)
session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
// Go to next whole hour down
SMPTE::hours_floor( smpte );
- for (n = 0; n < nmarks; n++) {
+ for (n = 0; n < smpte_nmarks; n++) {
session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
- if ((smpte.hours % mark_modulo) == 0) {
+ if ((smpte.hours % smpte_mark_modulo) == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
} else {
SMPTE::increment_hours( smpte );
}
- } else { // show_frames
+ break;
+ case smpte_show_frames:
// Find smpte time of this sample (pos)
session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
// Go to next whole frame down
SMPTE::frames_floor( smpte );
- for (n = 0; n < nmarks; n++) {
+ for (n = 0; n < smpte_nmarks; n++) {
session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
- if ((smpte.frames % mark_modulo) == 0) {
- (*marks)[n].style = GtkCustomRulerMarkMajor;
+ if ((smpte.frames % smpte_mark_modulo) == 0) {
+ if (smpte.frames == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ }
(*marks)[n].position = pos;
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
} else {
(*marks)[n].label = g_strdup (buf);
SMPTE::increment( smpte );
}
+
+ break;
}
- return nmarks;
+ return smpte_nmarks;
}
-gint
-Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::compute_bbt_ruler_scale (nframes_t lower, nframes_t upper)
{
if (session == 0) {
- return 0;
+ return;
}
-
TempoMap::BBTPointList::iterator i;
+ BBT_Time lower_beat, upper_beat; // the beats at each end of the ruler
+ session->bbt_time((jack_nframes_t) lower, lower_beat);
+ session->bbt_time((jack_nframes_t) upper, upper_beat);
uint32_t beats = 0;
- uint32_t bars = 0;
- uint32_t desirable_marks;
- uint32_t magic_accent_number = 1;
- gint nmarks;
- char buf[64];
- gint n = 0;
- nframes_t pos;
- bool bar_helper_on = true;
-
- BBT_Time next_beat;
- nframes_t next_beat_pos;
-
- if ((desirable_marks = maxchars / 7) == 0) {
- return 0;
- }
- /* align the tick marks to whatever we're snapping to... */
+ bbt_accent_modulo = 1;
+ bbt_bar_helper_on = false;
+ bbt_bars = 0;
+ bbt_nmarks = 1;
+ bbt_ruler_scale = bbt_over;
+
switch (snap_type) {
case SnapToAThirdBeat:
bbt_beat_subdivision = 3;
break;
case SnapToAEighthBeat:
bbt_beat_subdivision = 8;
- magic_accent_number = 2;
+ bbt_accent_modulo = 2;
break;
case SnapToASixteenthBeat:
bbt_beat_subdivision = 16;
- magic_accent_number = 4;
+ bbt_accent_modulo = 4;
break;
case SnapToAThirtysecondBeat:
bbt_beat_subdivision = 32;
- magic_accent_number = 8;
+ bbt_accent_modulo = 8;
break;
default:
- bbt_beat_subdivision = 4;
+ bbt_beat_subdivision = 4;
break;
}
if (current_bbt_points == 0 || current_bbt_points->empty()) {
- return 0;
+ return;
}
i = current_bbt_points->end();
i--;
- bars = (*i).bar - (*current_bbt_points->begin()).bar;
- beats = current_bbt_points->size() - bars;
+ if ((*i).beat >= (*current_bbt_points->begin()).beat) {
+ bbt_bars = (*i).bar - (*current_bbt_points->begin()).bar;
+ } else {
+ bbt_bars = (*i).bar - (*current_bbt_points->begin()).bar - 1;
+ }
+ beats = current_bbt_points->size() - bbt_bars;
/*Only show the bar helper if there aren't many bars on the screen */
- if (bars > 1) {
- bar_helper_on = false;
+ if ((bbt_bars < 2) || (beats < 5)) {
+ bbt_bar_helper_on = true;
}
- if (desirable_marks > (beats / 4)) {
+ if (bbt_bars > 8192) {
+ bbt_ruler_scale = bbt_over;
+ } else if (bbt_bars > 1024) {
+ bbt_ruler_scale = bbt_show_64;
+ } else if (bbt_bars > 256) {
+ bbt_ruler_scale = bbt_show_16;
+ } else if (bbt_bars > 64) {
+ bbt_ruler_scale = bbt_show_4;
+ } else if (bbt_bars > 10) {
+ bbt_ruler_scale = bbt_show_1;
+ } else if (bbt_bars > 2) {
+ bbt_ruler_scale = bbt_show_beats;
+ } else if (bbt_bars > 0) {
+ bbt_ruler_scale = bbt_show_ticks;
+ } else {
+ bbt_ruler_scale = bbt_show_ticks_detail;
+ }
- /* we're in beat land...*/
+ if ((bbt_ruler_scale == bbt_show_ticks_detail) && (lower_beat.beats == upper_beat.beats) && (upper_beat.ticks - lower_beat.ticks <= Meter::ticks_per_beat / 4)) {
+ bbt_ruler_scale = bbt_show_ticks_super_detail;
+ }
+}
- uint32_t tick = 0;
- uint32_t skip;
- uint32_t t;
- 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;
- bool helper_active = false;
-
- position_of_helper = lower + (30 * Editor::get_current_zoom ());
+gint
+Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+ if (session == 0) {
+ return 0;
+ }
- if (desirable_marks >= (beats)) {
- nmarks = (beats * bbt_beat_subdivision) + 1;
- we_need_ticks = true;
- } else {
- nmarks = beats + 1;
+ TempoMap::BBTPointList::iterator i;
+
+ char buf[64];
+ gint n = 0;
+ nframes_t pos;
+ BBT_Time next_beat;
+ nframes_t next_beat_pos;
+ uint32_t beats = 0;
+
+ uint32_t tick = 0;
+ uint32_t skip;
+ uint32_t t;
+ nframes_t frame_skip;
+ double frame_skip_error;
+ double bbt_position_of_helper;
+ double accumulated_error;
+ bool i_am_accented = false;
+ bool helper_active = false;
+
+ if (current_bbt_points == 0 || current_bbt_points->empty()) {
+ return 0;
+ }
+
+ switch (bbt_ruler_scale) {
+
+ case bbt_show_beats:
+ beats = current_bbt_points->size();
+ bbt_nmarks = beats + 2;
+
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+
+ (*marks)[0].label = g_strdup(" ");
+ (*marks)[0].position = lower;
+ (*marks)[0].style = GtkCustomRulerMarkMicro;
+
+ for (n = 1, i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+ if ((*i).type != TempoMap::Beat) {
+ continue;
+ }
+ if ((*i).frame < lower && (bbt_bar_helper_on)) {
+ snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+ (*marks)[0].label = g_strdup (buf);
+ helper_active = true;
+ } else {
+
+ if ((*i).beat == 1) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ } else if (((*i).beat % 2 == 1)) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ snprintf (buf, sizeof(buf), " ");
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ snprintf (buf, sizeof(buf), " ");
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
}
+ break;
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ case bbt_show_ticks:
+
+ beats = current_bbt_points->size();
+ bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
+
+ bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
(*marks)[0].label = g_strdup(" ");
(*marks)[0].position = lower;
(*marks)[0].style = GtkCustomRulerMarkMicro;
- for (n = 1, i = current_bbt_points->begin(); n < nmarks && i != current_bbt_points->end(); ++i) {
+ for (n = 1, i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+ if ((*i).type != TempoMap::Beat) {
+ continue;
+ }
+ if ((*i).frame < lower && (bbt_bar_helper_on)) {
+ snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+ (*marks)[0].label = g_strdup (buf);
+ helper_active = true;
+ } else {
- if ((*i).frame < lower && (bar_helper_on)) {
- snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
- (*marks)[0].label = g_strdup (buf);
- helper_active = true;
+ if ((*i).beat == 1) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+ }
+ if (((*i).frame < bbt_position_of_helper) && helper_active) {
+ snprintf (buf, sizeof(buf), " ");
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+
+ /* Add the tick marks */
+
+ /* Find the next beat */
+ next_beat.beats = (*i).beat;
+ next_beat.bars = (*i).bar;
+ next_beat.ticks = 0;
+
+ 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 = (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);
- if ((*i).type == TempoMap::Bar) {
- if (((*i).frame < position_of_helper) && helper_active) {
- snprintf (buf, sizeof(buf), " ");
- } else {
- snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
- }
- (*marks)[n].label = g_strdup (buf);
- (*marks)[n].position = (*i).frame;
- (*marks)[n].style = GtkCustomRulerMarkMajor;
- n++;
-
- } else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
- ((((*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) {
- (*marks)[n].style = GtkCustomRulerMarkMinor;
- } else {
- (*marks)[n].style = GtkCustomRulerMarkMicro;
- }
- (*marks)[n].label = g_strdup (buf);
- (*marks)[n].position = (*i).frame;
- n++;
- }
+ pos = (*i).frame + frame_skip;
+ accumulated_error = frame_skip_error;
+
+ tick = skip;
+
+ for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+
+ if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+ i_am_accented = true;
+ }
+
+ snprintf (buf, sizeof(buf), " ");
+ (*marks)[n].label = g_strdup (buf);
+ /* Error compensation for float to nframes_t*/
+ accumulated_error += frame_skip_error;
+ if (accumulated_error > 1) {
+ pos += 1;
+ accumulated_error -= 1.0f;
+ }
+
+ (*marks)[n].position = pos;
+
+ if ((bbt_beat_subdivision > 4) && i_am_accented) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ i_am_accented = false;
+ n++;
}
+ }
+ break;
- /* Add the tick marks */
+ case bbt_show_ticks_detail:
- if (we_need_ticks && (*i).type == TempoMap::Beat) {
+ beats = current_bbt_points->size();
+ bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
- /* Find the next beat */
+ bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
- next_beat.beats = (*i).beat;
- next_beat.bars = (*i).bar;
+ (*marks)[0].label = g_strdup(" ");
+ (*marks)[0].position = lower;
+ (*marks)[0].style = GtkCustomRulerMarkMicro;
+
+ for (n = 1, i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+ if ((*i).type != TempoMap::Beat) {
+ continue;
+ }
+ if ((*i).frame < lower && (bbt_bar_helper_on)) {
+ snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+ (*marks)[0].label = g_strdup (buf);
+ helper_active = true;
+ } else {
- if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
- next_beat.beats += 1;
+ if ((*i).beat == 1) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
} else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+ }
+ if (((*i).frame < bbt_position_of_helper) && helper_active) {
+ snprintf (buf, sizeof(buf), " ");
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+
+ /* Add the tick marks */
+
+ /* 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);
+ next_beat_pos = session->tempo_map().frame_time(next_beat);
+
+ frame_skip = (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);
- frame_skip = (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;
- pos = (*i).frame + frame_skip;
- accumulated_error = frame_skip_error;
+ tick = skip;
+
+ for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
- tick = skip;
-
- for (t = 0; (tick < Meter::ticks_per_beat) && (n < nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+ if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+ i_am_accented = true;
+ }
- if (t % magic_accent_number == (magic_accent_number - 1)) {
- i_am_accented = true;
- }
- if (Editor::get_current_zoom () > 32) {
- snprintf (buf, sizeof(buf), " ");
- } else if ((Editor::get_current_zoom () > 8) && !i_am_accented) {
- snprintf (buf, sizeof(buf), " ");
- } else if (bar_helper_on && (pos < position_of_helper)) {
- snprintf (buf, sizeof(buf), " ");
- } else {
- snprintf (buf, sizeof(buf), "%" PRIu32, tick);
- }
+ if (i_am_accented && (pos > bbt_position_of_helper)){
+ snprintf (buf, sizeof(buf), "%" PRIu32, tick);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ }
- (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].label = g_strdup (buf);
- /* Error compensation for float to nframes_t*/
- accumulated_error += frame_skip_error;
- if (accumulated_error > 1) {
- pos += 1;
- accumulated_error -= 1.0f;
- }
+ /* Error compensation for float to nframes_t*/
+ accumulated_error += frame_skip_error;
+ if (accumulated_error > 1) {
+ pos += 1;
+ accumulated_error -= 1.0f;
+ }
- (*marks)[n].position = pos;
+ (*marks)[n].position = pos;
- if ((bbt_beat_subdivision > 4) && i_am_accented) {
- (*marks)[n].style = GtkCustomRulerMarkMinor;
- } else {
- (*marks)[n].style = GtkCustomRulerMarkMicro;
- }
- i_am_accented = false;
- n++;
-
+ if ((bbt_beat_subdivision > 4) && i_am_accented) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
}
+ i_am_accented = false;
+ n++;
}
}
- return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures
- } else {
+ break;
+
+ case bbt_show_ticks_super_detail:
- /* we're in bar land */
+ beats = current_bbt_points->size();
+ bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
- if (desirable_marks < (bars / 256)) {
- nmarks = 1;
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
- snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", bars );
+ bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+
+ (*marks)[0].label = g_strdup(" ");
+ (*marks)[0].position = lower;
+ (*marks)[0].style = GtkCustomRulerMarkMicro;
+
+ for (n = 1, i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+ if ((*i).type != TempoMap::Beat) {
+ continue;
+ }
+ if ((*i).frame < lower && (bbt_bar_helper_on)) {
+ snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+ (*marks)[0].label = g_strdup (buf);
+ helper_active = true;
+ } else {
+
+ if ((*i).beat == 1) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+ }
+ if (((*i).frame < bbt_position_of_helper) && helper_active) {
+ snprintf (buf, sizeof(buf), " ");
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+
+ /* Add the tick marks */
+
+ /* 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 = (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;
+
+ for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+
+ if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+ i_am_accented = true;
+ }
+
+ if (pos > bbt_position_of_helper) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, tick);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ }
+
+ (*marks)[n].label = g_strdup (buf);
+
+ /* Error compensation for float to nframes_t*/
+ accumulated_error += frame_skip_error;
+ if (accumulated_error > 1) {
+ pos += 1;
+ accumulated_error -= 1.0f;
+ }
+
+ (*marks)[n].position = pos;
+
+ if ((bbt_beat_subdivision > 4) && i_am_accented) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ i_am_accented = false;
+ n++;
+ }
+ }
+
+ break;
+
+ case bbt_over:
+ bbt_nmarks = 1;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+ snprintf (buf, sizeof(buf), "cannot handle %" PRIu32 " bars", bbt_bars );
(*marks)[0].style = GtkCustomRulerMarkMajor;
(*marks)[0].label = g_strdup (buf);
(*marks)[0].position = lower;
- } else if (desirable_marks < (uint32_t)(nmarks = (gint) (bars / 64) + 1)) {
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
- for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
+ n = 1;
+
+ break;
+
+ case bbt_show_64:
+ bbt_nmarks = (gint) (bbt_bars / 64) + 1;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+ for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
if ((*i).type == TempoMap::Bar) {
if ((*i).bar % 64 == 1) {
if ((*i).bar % 256 == 1) {
}
}
}
- } else if (desirable_marks < (uint32_t)(nmarks = (bars / 16) + 1)) {
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
- 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) {
- snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
- (*marks)[n].style = GtkCustomRulerMarkMajor;
- } else {
- snprintf (buf, sizeof(buf), " ");
- if ((*i).bar % 64 == 33) {
- (*marks)[n].style = GtkCustomRulerMarkMinor;
- } else {
- (*marks)[n].style = GtkCustomRulerMarkMicro;
- }
- }
- (*marks)[n].label = g_strdup (buf);
- (*marks)[n].position = (*i).frame;
- n++;
+ break;
+
+ case bbt_show_16:
+ bbt_nmarks = (bbt_bars / 16) + 1;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+ for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 16 == 1) {
+ if ((*i).bar % 64 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 64 == 33) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
}
}
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
}
- } else if (desirable_marks < (uint32_t)(nmarks = (bars / 4) + 1)){
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
- 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) {
- snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
- (*marks)[n].style = GtkCustomRulerMarkMajor;
- } else {
- snprintf (buf, sizeof(buf), " ");
- if ((*i).bar % 16 == 9) {
- (*marks)[n].style = GtkCustomRulerMarkMinor;
- } else {
- (*marks)[n].style = GtkCustomRulerMarkMicro;
- }
- }
- (*marks)[n].label = g_strdup (buf);
- (*marks)[n].position = (*i).frame;
- n++;
+ }
+ break;
+
+ case bbt_show_4:
+ bbt_nmarks = (bbt_bars / 4) + 1;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+ for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; ++i) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 4 == 1) {
+ if ((*i).bar % 16 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 16 == 9) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
}
}
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
}
- } else {
- nmarks = bars + 1;
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks );
- 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);
- (*marks)[n].style = GtkCustomRulerMarkMajor;
- } else {
- snprintf (buf, sizeof(buf), " ");
- if ((*i).bar % 4 == 3) {
- (*marks)[n].style = GtkCustomRulerMarkMinor;
- } else {
- (*marks)[n].style = GtkCustomRulerMarkMicro;
- }
- }
- (*marks)[n].label = g_strdup (buf);
- (*marks)[n].position = (*i).frame;
- n++;
- }
- }
- }
- return n;
+ }
+ break;
+
+ case bbt_show_1:
+ // default:
+ bbt_nmarks = bbt_bars + 2;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks );
+ for (n = 0, i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 4 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 4 == 3) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+ }
+
+ break;
+
}
+
+ return n; //return the actual number of marks made, since we might have skipped some from fractional time signatures
+
}
gint
return;
}
-gint
-Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper)
{
nframes_t range;
nframes_t fr;
- nframes_t mark_interval;
- nframes_t pos;
nframes_t spacer;
- long hrs, mins, secs, millisecs;
- gchar buf[16];
- gint nmarks;
- gint n;
- gint mark_modulo = 100;
- bool show_seconds = false;
- bool show_minutes = false;
- bool show_hours = false;
- nframes_t ilower = (nframes_t) floor (lower);
- nframes_t iupper = (nframes_t) floor (upper);
if (session == 0) {
- return 0;
+ return;
}
fr = session->frame_rate();
/* to prevent 'flashing' */
if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
- lower = lower - spacer;
+ lower -= spacer;
} else {
lower = 0;
}
- upper = upper + spacer;
- range = iupper - ilower;
+ upper += spacer;
+ range = (nframes_t) (upper - lower);
if (range < (fr / 50)) {
- mark_interval = fr / 100; /* show 1/100 seconds */
- mark_modulo = 10;
+ minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 10;
} else if (range <= (fr / 10)) { /* 0-0.1 second */
- mark_interval = fr / 50; /* show 1/50 seconds */
- mark_modulo = 20;
+ minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 10;
} else if (range <= (fr / 2)) { /* 0-0.5 second */
- mark_interval = fr / 20; /* show 1/20 seconds */
- mark_modulo = 100;
+ minsec_mark_interval = fr / 100; /* show 1/100 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 100;
} else if (range <= fr) { /* 0-1 second */
- mark_interval = fr / 10; /* show 1/10 seconds */
- mark_modulo = 200;
+ minsec_mark_interval = fr / 10; /* show 1/10 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 200;
} else if (range <= 2 * fr) { /* 1-2 seconds */
- mark_interval = fr / 2; /* show 1/2 seconds */
- mark_modulo = 500;
+ minsec_mark_interval = fr / 10; /* show 1/10 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 500;
} else if (range <= 8 * fr) { /* 2-5 seconds */
- mark_interval = fr / 5; /* show 2 seconds */
- mark_modulo = 1000;
+ minsec_mark_interval = fr / 5; /* show 2 seconds */
+ minsec_ruler_scale = minsec_show_frames;
+ minsec_mark_modulo = 1000;
} else if (range <= 16 * fr) { /* 8-16 seconds */
- mark_interval = fr; /* show 1 seconds */
- show_seconds = true;
- mark_modulo = 5;
+ minsec_mark_interval = fr; /* show 1 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 2;
} else if (range <= 30 * fr) { /* 10-30 seconds */
- mark_interval = fr; /* show 10 seconds */
- show_seconds = true;
- mark_modulo = 5;
+ minsec_mark_interval = fr; /* show 1 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 5;
} else if (range <= 60 * fr) { /* 30-60 seconds */
- mark_interval = 5 * fr; /* show 5 seconds */
- show_seconds = true;
- mark_modulo = 3;
+ minsec_mark_interval = fr; /* show 1 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 5;
} else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
- mark_interval = 5 * fr; /* show 5 seconds */
- show_seconds = true;
- mark_modulo = 3;
+ minsec_mark_interval = 5 * fr; /* show 5 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 3;
} else if (range <= 4 * 60 * fr) { /* 4 minutes */
- mark_interval = 10 * fr; /* show 10 seconds */
- show_seconds = true;
- mark_modulo = 30;
+ minsec_mark_interval = 5 * fr; /* show 10 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 30;
} else if (range <= 10 * 60 * fr) { /* 10 minutes */
- mark_interval = 30 * fr; /* show 30 seconds */
- show_seconds = true;
- mark_modulo = 60;
+ minsec_mark_interval = 30 * fr; /* show 30 seconds */
+ minsec_ruler_scale = minsec_show_seconds;
+ minsec_mark_modulo = 120;
} else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
- mark_interval = 60 * fr; /* show 1 minute */
- show_minutes = true;
- mark_modulo = 5;
+ minsec_mark_interval = 60 * fr; /* show 1 minute */
+ minsec_ruler_scale = minsec_show_minutes;
+ minsec_mark_modulo = 5;
} else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
- mark_interval = 2 * 60 * fr; /* show 2 minutes */
- show_minutes = true;
- mark_modulo = 10;
+ minsec_mark_interval = 2 * 60 * fr; /* show 2 minutes */
+ minsec_ruler_scale = minsec_show_minutes;
+ minsec_mark_modulo = 10;
} else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
- mark_interval = 5 * 60 * fr; /* show 10 minutes */
- show_minutes = true;
- mark_modulo = 30;
+ minsec_mark_interval = 5 * 60 * fr; /* show 10 minutes */
+ minsec_ruler_scale = minsec_show_minutes;
+ minsec_mark_modulo = 30;
} else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
- mark_interval = 20 * 60 * fr; /* show 20 minutes */
- show_minutes = true;
- mark_modulo = 60;
+ minsec_mark_interval = 20 * 60 * fr; /* show 20 minutes */
+ minsec_ruler_scale = minsec_show_minutes;
+ minsec_mark_modulo = 60;
} else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
- mark_interval = 60 * 60 * fr; /* show 60 minutes */
- show_hours = true;
- mark_modulo = 2;
+ minsec_mark_interval = 60 * 60 * fr; /* show 60 minutes */
+ minsec_ruler_scale = minsec_show_hours;
+ minsec_mark_modulo = 2;
} else {
/* not possible if nframes_t is a 32 bit quantity */
- mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */
+ minsec_mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */
}
+ minsec_nmarks = 2 + (range / minsec_mark_interval);
+}
- nmarks = 1 + (range / mark_interval);
- *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
- pos = ((ilower + (mark_interval/2))/mark_interval) * mark_interval;
-
- if (show_seconds) {
- for (n = 0; n < nmarks; pos += mark_interval, ++n) {
- sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
- if (secs % mark_modulo == 0) {
+gint
+Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+ nframes_t pos;
+ nframes_t spacer;
+ long hrs, mins, secs, millisecs;
+ gchar buf[16];
+ gint n;
+
+ if (session == 0) {
+ return 0;
+ }
+
+ /* to prevent 'flashing' */
+ if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
+ lower = lower - spacer;
+ } else {
+ lower = 0;
+ }
+
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * minsec_nmarks);
+ pos = ((((nframes_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval;
+ switch (minsec_ruler_scale) {
+ case minsec_show_seconds:
+ for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+ sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+ if (secs % minsec_mark_modulo == 0) {
if (secs == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
} else {
(*marks)[n].label = g_strdup (buf);
(*marks)[n].position = pos;
}
- } else if (show_minutes) {
- for (n = 0; n < nmarks; pos += mark_interval, ++n) {
- sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
- if (mins % mark_modulo == 0) {
+ break;
+ case minsec_show_minutes:
+ for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+ sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+ if (mins % minsec_mark_modulo == 0) {
if (mins == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
} else {
(*marks)[n].label = g_strdup (buf);
(*marks)[n].position = pos;
}
- } else if (show_hours) {
- for (n = 0; n < nmarks; pos += mark_interval, ++n) {
- sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
- if (hrs % mark_modulo == 0) {
+ break;
+ case minsec_show_hours:
+ for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+ sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+ if (hrs % minsec_mark_modulo == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
} else {
(*marks)[n].label = g_strdup (buf);
(*marks)[n].position = pos;
}
- } else {
- for (n = 0; n < nmarks; pos += mark_interval, ++n) {
- sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
- if (millisecs % mark_modulo == 0) {
- if (millisecs == 0) {
+ break;
+ case minsec_show_frames:
+ for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+ sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+ if (millisecs % minsec_mark_modulo == 0) {
+ if (secs == 0) {
(*marks)[n].style = GtkCustomRulerMarkMajor;
} else {
(*marks)[n].style = GtkCustomRulerMarkMinor;
(*marks)[n].label = g_strdup (buf);
(*marks)[n].position = pos;
}
+ break;
}
- return nmarks;
+ return minsec_nmarks;
}
return;
}
- ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored));
-
- redisplay_tempo (false); // redraw rulers and measures
+ ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored));
+
+ compute_current_bbt_points(leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
+ update_tempo_based_rulers ();
+ if (tempo_map_change_idle_handler_id < 0) {
+ tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
+ }
}
-/**
- * This code was originally in tempo_map_changed, but this is called every time the canvas scrolls horizontally.
- * That's why this is moved in here. The new tempo_map_changed is called when the ARDOUR::TempoMap actually changed.
- */
void
Editor::redisplay_tempo (bool immediate_redraw)
+{
+ if (!session) {
+ return;
+ }
+
+ compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit)); // redraw rulers and measures
+
+ if (immediate_redraw) {
+
+ hide_measures ();
+
+ if (current_bbt_points) {
+ draw_measures ();
+ }
+
+ } else if (tempo_map_change_idle_handler_id < 0) {
+
+ tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
+
+ }
+
+ update_tempo_based_rulers ();
+}
+
+void
+Editor::compute_current_bbt_points (nframes_t leftmost, nframes_t rightmost)
{
if (!session) {
return;
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);
+ session->bbt_time(leftmost, previous_beat);
+ session->bbt_time(rightmost, next_beat);
if (previous_beat.beats > 1) {
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) {
+ if (session->tempo_map().meter_at(rightmost).beats_per_bar () > next_beat.beats + 1) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
current_bbt_points = 0;
}
- if (session) {
- 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;
- }
-
- if (immediate_redraw) {
-
- hide_measures ();
-
- if (session && current_bbt_points) {
- draw_measures ();
- }
-
- } else {
-
- if (session && current_bbt_points) {
- Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
- } else {
- hide_measures ();
- }
- }
+ current_bbt_points = session->tempo_map().get_points (session->tempo_map().frame_time (previous_beat), session->tempo_map().frame_time (next_beat) + 1);
}
void
{
hide_measures ();
draw_measures ();
+ tempo_map_change_idle_handler_id = -1;
return false;
}
#include <ardour/audio_track.h>
#include <ardour/audioregion.h>
#include <ardour/audioengine.h>
+#include <ardour/audiofilesource.h>
#include <ardour/gdither.h>
#include <ardour/utils.h>
};
static const gchar* channel_strings[] = {
- N_("stereo"),
- N_("mono"),
+ N_("Stereo"),
+ N_("Mono"),
0
};
src_quality_label (_("Conversion Quality"), 1.0, 0.5),
dither_type_label (_("Dither Type"), 1.0, 0.5),
cuefile_only_checkbox (_("Export CD Marker File Only")),
- file_browse_button (_("Browse")),
+ file_chooser (FILE_CHOOSER_ACTION_SAVE),
track_selector_button (_("Specific tracks ..."))
{
guint32 n;
track_and_master_selection_allowed = true;
channel_count_selection_allowed = true;
export_cd_markers_allowed = true;
+ set_resizable (false);
WindowTitle title(Glib::get_application_name());
title += _("Export");
spec.running = false;
- file_entry.set_name ("ExportFileNameEntry");
-
master_list = ListStore::create (exp_cols);
master_selector.set_model (master_list);
track_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
master_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
- get_vbox()->pack_start (file_frame, false, false);
+ get_vbox()->pack_start (file_frame, PACK_EXPAND_WIDGET);
hpacker.set_spacing (5);
hpacker.set_border_width (5);
- hpacker.pack_start (format_frame, false, false);
+ hpacker.pack_start (format_frame, PACK_SHRINK );
master_scroll.add (master_selector);
track_scroll.add (track_selector);
hpacker.pack_start (track_vpacker);
- get_vbox()->pack_start (hpacker);
+ get_vbox()->pack_start (hpacker, PACK_SHRINK);
track_selector_button.set_name ("EditorGTKButton");
track_selector_button.signal_clicked().connect (mem_fun(*this, &ExportDialog::track_selector_button_click));
- get_vbox()->pack_start (progress_bar, false, false);
+ Gtk::FileFilter filter_wav;
+ filter_wav.set_name("Wav files");
+ filter_wav.add_mime_type("audio/wav");
+ file_chooser.add_filter(filter_wav);
+
+ Gtk::FileFilter filter_aiff;
+ filter_aiff.set_name("Aiff files");
+ filter_aiff.add_mime_type("audio/aiff");
+ filter_aiff.add_pattern("*.aif");
+ filter_aiff.add_pattern("*.aiff");
+ file_chooser.add_filter(filter_aiff);
+
+ Gtk::FileFilter filter_any;
+ filter_any.set_name("All files");
+ filter_any.add_pattern("*");
+ file_chooser.add_filter(filter_any);
+ file_chooser.set_no_show_all();
- Gtkmm2ext::set_size_request_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
+ get_vbox()->pack_start (progress_bar, false, false, 5);
+ progress_bar.set_no_show_all();
+ progress_bar.hide();
file_hbox.set_spacing (5);
file_hbox.set_border_width (5);
- file_hbox.pack_start (file_entry, true, true);
- file_hbox.pack_start (file_browse_button, false, false);
+ file_hbox.pack_start (file_chooser, PACK_EXPAND_WIDGET);
file_frame.add (file_hbox);
file_frame.set_border_width (5);
cuefile_only_checkbox.set_name ("ExportCheckbox");
- format_table.set_homogeneous (false);
+ format_table.set_homogeneous (true);
format_table.set_border_width (5);
format_table.set_col_spacings (5);
format_table.set_row_spacings (5);
- format_table.attach (channel_count_label, 0, 1, 0, 1);
- format_table.attach (channel_count_combo, 1, 2, 0, 1);
+ format_table.attach (channel_count_label, 0, 1, 0, 1, FILL, FILL);
+ format_table.attach (channel_count_combo, 1, 2, 0, 1, FILL, FILL);
- format_table.attach (header_format_label, 0, 1, 1, 2);
- format_table.attach (header_format_combo, 1, 2, 1, 2);
+ format_table.attach (header_format_label, 0, 1, 1, 2, FILL, FILL);
+ format_table.attach (header_format_combo, 1, 2, 1, 2, FILL, FILL);
- format_table.attach (bitdepth_format_label, 0, 1, 2, 3);
- format_table.attach (bitdepth_format_combo, 1, 2, 2, 3);
+ format_table.attach (bitdepth_format_label, 0, 1, 2, 3, FILL, FILL);
+ format_table.attach (bitdepth_format_combo, 1, 2, 2, 3, FILL, FILL);
- format_table.attach (endian_format_label, 0, 1, 3, 4);
- format_table.attach (endian_format_combo, 1, 2, 3, 4);
+ format_table.attach (endian_format_label, 0, 1, 3, 4, FILL, FILL);
+ format_table.attach (endian_format_combo, 1, 2, 3, 4, FILL, FILL);
- format_table.attach (sample_rate_label, 0, 1, 4, 5);
- format_table.attach (sample_rate_combo, 1, 2, 4, 5);
+ format_table.attach (sample_rate_label, 0, 1, 4, 5, FILL, FILL);
+ format_table.attach (sample_rate_combo, 1, 2, 4, 5, FILL, FILL);
- format_table.attach (src_quality_label, 0, 1, 5, 6);
- format_table.attach (src_quality_combo, 1, 2, 5, 6);
+ format_table.attach (src_quality_label, 0, 1, 5, 6, FILL, FILL);
+ format_table.attach (src_quality_combo, 1, 2, 5, 6, FILL, FILL);
- format_table.attach (dither_type_label, 0, 1, 6, 7);
- format_table.attach (dither_type_combo, 1, 2, 6, 7);
+ format_table.attach (dither_type_label, 0, 1, 6, 7, FILL, FILL);
+ format_table.attach (dither_type_combo, 1, 2, 6, 7, FILL, FILL);
- format_table.attach (cue_file_label, 0, 1, 7, 8);
- format_table.attach (cue_file_combo, 1, 2, 7, 8);
- format_table.attach (cuefile_only_checkbox, 0, 2, 8, 9);
-
- file_entry.set_name ("ExportFileDisplay");
+ format_table.attach (cue_file_label, 0, 1, 7, 8, FILL, FILL);
+ format_table.attach (cue_file_combo, 1, 2, 7, 8, FILL, FILL);
+ format_table.attach (cuefile_only_checkbox, 0, 2, 8, 9, FILL, FILL);
signal_delete_event().connect (mem_fun(*this, &ExportDialog::window_closed));
cancel_button->signal_clicked().connect (mem_fun(*this, &ExportDialog::end_dialog));
ok_button = add_button (_("Export"), RESPONSE_ACCEPT);
ok_button->signal_clicked().connect (mem_fun(*this, &ExportDialog::do_export));
-
- file_browse_button.set_name ("EditorGTKButton");
- file_browse_button.signal_clicked().connect (mem_fun(*this, &ExportDialog::browse));
-
channel_count_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::channels_chosen));
bitdepth_format_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::bitdepth_chosen));
header_format_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::header_chosen));
sample_rate_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::sample_rate_chosen));
cue_file_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::cue_file_type_chosen));
+
+ file_chooser.signal_update_preview().connect (mem_fun(*this, &ExportDialog::file_chooser_selection_changed));
+
}
ExportDialog::~ExportDialog()
ExportDialog::do_not_allow_track_and_master_selection()
{
track_and_master_selection_allowed = false;
- track_vpacker.set_no_show_all();
}
void
ExportDialog::do_not_allow_channel_count_selection()
{
channel_count_selection_allowed = false;
- channel_count_combo.set_no_show_all();
- channel_count_label.set_no_show_all();
}
void
ExportDialog::do_not_allow_export_cd_markers()
{
export_cd_markers_allowed = false;
- cue_file_label.set_no_show_all();
- cue_file_combo.set_no_show_all();
- cuefile_only_checkbox.set_no_show_all();
}
void
{
XMLNode* node = session->instant_xml(X_("ExportDialog"));
XMLProperty* prop;
-
+ bool fc_location_requested = false;
if (node) {
if ((prop = node->property (X_("sample_rate"))) != 0) {
endian_format_combo.set_active_text(prop->value());
}
if ((prop = node->property (X_("filename"))) != 0) {
- file_entry.set_text(prop->value());
+ file_chooser.set_filename(prop->value());
+ fc_location_requested = true;
+ file_chooser.set_current_folder(Glib::path_get_basename(prop->value()));
}
+
if ((prop = node->property (X_("cue_file_type"))) != 0) {
cue_file_combo.set_active_text(prop->value());
}
}
+ if (!fc_location_requested) {
+
+ /*
+ If the filename hasn't been set before, use the
+ current session's export directory as a default
+ location for the export.
+ */
+
+ file_chooser.set_current_folder (session->session_directory().export_path().to_string());
+ file_chooser.set_current_name (_("export.wav"));
+ }
+
header_chosen ();
bitdepth_chosen();
channels_chosen();
if (!master) {
/* default is to use all */
- if (channel_count_combo.get_active_text() == _("mono")) {
+ if (channel_count_combo.get_active_text() == _("Mono")) {
nchns = 1;
} else {
nchns = 2;
node->add_property(X_("header_format"), header_format_combo.get_active_text());
node->add_property(X_("bitdepth_format"), bitdepth_format_combo.get_active_text());
node->add_property(X_("endian_format"), endian_format_combo.get_active_text());
- node->add_property(X_("filename"), file_entry.get_text());
+ node->add_property(X_("filename"), file_chooser.get_filename());
node->add_property(X_("cue_file_type"), cue_file_combo.get_active_text());
XMLNode* tracks = new XMLNode(X_("Tracks"));
void
ExportDialog::do_export ()
{
- string filepath = file_entry.get_text();
+ string filepath = file_chooser.get_filename();
if(!is_filepath_valid(filepath)){
return;
if (export_cd_markers_allowed) {
if (cue_file_combo.get_active_text () != _("None")) {
- do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
+ do_export_cd_markers (file_chooser.get_filename(), cue_file_combo.get_active_text ());
}
if (cuefile_only_checkbox.get_active()) {
// read user input into spec
initSpec(filepath);
+ progress_bar.show();
progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100);
cancel_label.set_text (_("Stop Export"));
export_audio_data();
progress_connection.disconnect ();
+ session->engine().freewheel (false);
+ progress_bar.hide();
end_dialog ();
}
}
}
- session->finalize_audio_export ();
+ hide ();
- hide_all ();
+ session->finalize_audio_export ();
set_modal (false);
ok_button->set_sensitive(true);
file_entry.set_text (export_file_path.to_string());
}
-
+
progress_bar.set_fraction (0);
+ progress_bar.hide();
+ progress_bar.set_no_show_all();
cancel_label.set_text (_("Cancel"));
- show_all ();
+ show_all();
+
+ if (track_and_master_selection_allowed) {
+ track_vpacker.show();
+ } else {
+ track_vpacker.hide();
+ }
+
+ file_chooser.show();
+
+ if (channel_count_selection_allowed) {
+ channel_count_combo.show();
+ channel_count_label.show();
+ } else {
+ channel_count_combo.hide();
+ channel_count_label.hide();
+ }
+
+ if (export_cd_markers_allowed) {
+ cue_file_label.show();
+ cue_file_combo.show();
+ cuefile_only_checkbox.show();
+ } else {
+ cue_file_label.hide();
+ cue_file_combo.hide();
+ cuefile_only_checkbox.hide();
+ }
if (session->master_out()) {
track_scroll.hide ();
master_scroll.hide ();
track_selector_button.hide ();
}
+
+ track_and_master_selection_allowed = true;
+ channel_count_selection_allowed = true;
+ export_cd_markers_allowed = true;
}
void
ExportDialog::header_chosen ()
{
if (sndfile_header_format_from_string (header_format_combo.get_active_text ()) == SF_FORMAT_WAV) {
+ endian_format_combo.set_active_text (N_("Little-endian (Intel)"));
endian_format_combo.set_sensitive (false);
} else {
endian_format_combo.set_sensitive (true);
+ endian_format_combo.set_active_text (N_("Big-endian (Mac)"));
}
}
}
}
+void
+ExportDialog::file_chooser_selection_changed ()
+{
+
+ /*
+ if the user selects an existing file from the 'browse for other folders' tab,
+ change the format settings to match the file.
+ */
+ if (file_chooser.get_filename().length() == 0) {
+ return;
+ }
+ if (Glib::file_test(file_chooser.get_preview_filename(),Glib::FILE_TEST_IS_DIR)){
+ file_chooser.set_current_name (_(""));
+ return;
+ }
+ if (!Glib::file_test(file_chooser.get_preview_filename(),Glib::FILE_TEST_EXISTS)) {
+ return;
+ }
+
+ SoundFileInfo finfo;
+ string error_msg, format_str;
+
+ if (!AudioFileSource::get_soundfile_info (file_chooser.get_preview_filename(), finfo, error_msg)) {
+ error << string_compose(_("Export: cannot open file \"%1\"."), error_msg ) << endmsg;
+ return;
+ }
+
+ if (finfo.samplerate == 22050) {
+ sample_rate_combo.set_active_text (N_("22.05kHz"));
+ } else if (finfo.samplerate == 44100) {
+ sample_rate_combo.set_active_text (N_("44.1kHz"));
+ } else if (finfo.samplerate == 48000) {
+ sample_rate_combo.set_active_text (N_("48kHz"));
+ } else if (finfo.samplerate == 88200) {
+ sample_rate_combo.set_active_text (N_("88.2kHz"));
+ } else if (finfo.samplerate == 96000) {
+ sample_rate_combo.set_active_text (N_("96kHz"));
+ } else if (finfo.samplerate == 192000) {
+ sample_rate_combo.set_active_text (N_("192kHz"));
+ }
+
+ if (finfo.channels == 1) {
+ channel_count_combo.set_active_text(N_("Mono"));
+ } else {
+ channel_count_combo.set_active_text(N_("Stereo"));
+ }
+
+ string::size_type pos;
+
+ pos = finfo.format_name.find_first_of (" ");
+ format_str = finfo.format_name.substr(pos + 1, 255);
+ pos = format_str.find_first_of (" ");
+ header_format_combo.set_active_text(format_str.substr(0, pos));
+
+ format_str = finfo.format_name;
+ pos = format_str.find_first_of (",");
+ bitdepth_format_combo.set_active_text(format_str.substr(pos + 2, 255));
+}
+
void
ExportDialog::sample_rate_chosen ()
{
{
bool mono;
- mono = (channel_count_combo.get_active_text() == _("mono"));
+ mono = (channel_count_combo.get_active_text() == _("Mono"));
if (mono) {
track_selector.get_column(2)->set_visible(false);
return false;
}
else {
- string txt = _("File already exists, do you want to overwrite it?");
+ string txt = _("File ") + filepath + _(" already exists, do you want to overwrite it?");
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
return false;
spec.stop = false;
spec.port_map.clear();
- if (channel_count_combo.get_active_text() == _("mono")) {
+ if (channel_count_combo.get_active_text() == _("Mono")) {
spec.channels = 1;
} else {
spec.channels = 2;
return TRUE;
}
-void
-ExportDialog::browse ()
-{
- FileChooserDialog dialog("Export to file", browse_action());
- dialog.set_transient_for(*this);
- dialog.set_filename (file_entry.get_text());
-
- dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
- dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
-
- int result = dialog.run();
-
- if (result == Gtk::RESPONSE_OK) {
- string filename = dialog.get_filename();
-
- if (filename.length()) {
- file_entry.set_text (filename);
- }
- }
-}
-
void
ExportDialog::track_selector_button_click ()
{
Gtk::Entry file_entry;
Gtk::HBox file_hbox;
- Gtk::Button file_browse_button;
+ Gtk::FileChooserWidget file_chooser;
Gtk::Button* ok_button;
Gtk::Button* cancel_button;
void bitdepth_chosen ();
void sample_rate_chosen ();
void cue_file_type_chosen();
+ void file_chooser_selection_changed();
void fill_lists();
void write_track_and_master_selection_to_spec();
void track_selector_button_click ();
- void browse ();
-
void set_state();
void save_state();
};
sync_mark->property_fill_color_rgba() = fill_color;
sync_mark->hide();
- reset_width_dependent_items ((double) _region->length() / samples_per_unit);
+ //reset_width_dependent_items ((double) _region->length() / samples_per_unit);
if (wfd)
_enable_display = true;
if (what_changed & Region::SyncOffsetChanged) {
region_sync_changed ();
}
+ /*
+ this should not be needed now that only playlist can change layering
+ */
+ /*
if (what_changed & Region::LayerChanged) {
region_layered ();
}
+ */
if (what_changed & Region::LockChanged) {
region_locked ();
}
void
StreamView::region_layered (RegionView* rv)
{
- rv->get_canvas_group()->lower_to_bottom();
- /* don't ever leave it at the bottom, since then it doesn't
- get events - the parent group does instead ...
- */
-
- /* this used to be + 1, but regions to the left ended up below
- ..something.. and couldn't receive events. why? good question.
- */
- /* and now it's + 3 for midi note separator lines */
- rv->get_canvas_group()->raise (rv->region()->layer() + 3);
+ /*
+ Currently 'layer' has nothing to do with the desired canvas layer.
+ For now, ensure that multiple regionviews passed here in groups are
+ ordered by 'layer' (lowest to highest).
+
+ (see AudioStreamView::redisplay_diskstream ()).
+
+ We move them to the top layer as they arrive.
+ */
+
+ rv->get_canvas_group()->raise_to_top();
}
void
context.Result(result)
return result
-#
-# See if JACK supports jack_port_ensure_monitor_input()
-#
-jack_ensure_monitor_input_test = """
-#include <jack/jack.h>
-int main(int argc, char** argv)
-{
- jack_port_t **port;
-
- jack_port_ensure_monitor (*port, 1);
- return 0;
-
-}
-"""
-
-def CheckJackEnsureMonitorInput(context):
- context.Message('Checking for jack_port_ensure_monitor_input()...')
- result = context.TryLink(jack_ensure_monitor_input_test, '.c')
- context.Result(result)
- return result
-
conf = Configure(ardour, custom_tests = {
'CheckJackClientOpen' : CheckJackClientOpen,
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
'CheckJackRecomputeLatency' : CheckJackRecomputeLatency,
- 'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset,
- 'CheckJackEnsureMonitorInput' : CheckJackEnsureMonitorInput
+ 'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset
})
if conf.CheckJackClientOpen():
if conf.CheckJackVideoFrameOffset():
ardour.Append(CXXFLAGS="-DHAVE_JACK_VIDEO_SUPPORT")
-
-if conf.CheckJackEnsureMonitorInput():
- ardour.Append(CXXFLAGS='-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
/* returns the number of items in this `audio_source' */
- virtual nframes_t length() const {
- return _length;
- }
-
virtual nframes_t available_peaks (double zoom) const;
virtual nframes_t read (Sample *dst, nframes_t start, nframes_t cnt) const;
bool _peaks_built;
mutable Glib::Mutex _lock;
mutable Glib::Mutex _peaks_ready_lock;
- nframes_t _length;
Glib::ustring peakpath;
Glib::ustring _captured_for;
}
void ensure_monitor_input (bool yn) {
-
-#ifdef HAVE_JACK_PORT_ENSURE_MONITOR
jack_port_ensure_monitor (_port, yn);
-#else
- jack_port_request_monitor(_port, yn);
-#endif
-
}
/*XXX completely bloody useless imho*/
enum MonitorModel {
HardwareMonitoring,
SoftwareMonitoring,
- ExternalMonitoring,
+ ExternalMonitoring
};
enum DenormalModel {
enum RemoteModel {
UserOrdered,
MixerOrdered,
- EditorOrdered,
+ EditorOrdered
};
enum CrossfadeModel {
boost::shared_ptr<AudioRegion> top;
boost::shared_ptr<AudioRegion> bottom;
boost::shared_ptr<Crossfade> xfade;
+ RegionList* touched_regions;
if (in_set_state || in_partition) {
return;
break;
case OverlapExternal:
-
+
/* [ -------- top ------- ]
* {=========== bottom =============}
*/
*/
xfade_length = min ((nframes_t) 720, top->length());
-
- xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
- add_crossfade (xfade);
+
+ if (top_region_at (top->first_frame()) == top) {
+
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
+ add_crossfade (xfade);
+ }
if (top_region_at (top->last_frame() - 1) == top) {
+
/*
only add a fade out if there is no region on top of the end of 'top' (which
would cover it).
add_crossfade (xfade);
}
break;
-
+ case OverlapStart:
+
+ /* { ==== top ============ }
+ * [---- bottom -------------------]
+ */
+
+ if (Config->get_xfade_model() == FullCrossfade) {
+ touched_regions = regions_touched (top->first_frame(), bottom->last_frame());
+ if (touched_regions->size() <= 2) {
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+ add_crossfade (xfade);
+ }
+ } else {
+
+ touched_regions = regions_touched (top->first_frame(),
+ top->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(),
+ top->length()));
+ if (touched_regions->size() <= 2) {
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+ add_crossfade (xfade);
+ }
+ }
+ break;
+ case OverlapEnd:
+
+
+ /* [---- top ------------------------]
+ * { ==== bottom ============ }
+ */
+
+ if (Config->get_xfade_model() == FullCrossfade) {
+
+ touched_regions = regions_touched (bottom->first_frame(), top->last_frame());
+ if (touched_regions->size() <= 2) {
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other,
+ Config->get_xfade_model(), Config->get_xfades_active()));
+ add_crossfade (xfade);
+ }
+
+ } else {
+ touched_regions = regions_touched (bottom->first_frame(),
+ bottom->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(),
+ bottom->length()));
+ if (touched_regions->size() <= 2) {
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+ add_crossfade (xfade);
+ }
+ }
+ break;
default:
- xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+ xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other,
+ Config->get_xfade_model(), Config->get_xfades_active()));
add_crossfade (xfade);
}
}
if (g_atomic_int_get(&block_notifications)) {
_pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
} else {
+
NewCrossfade (x); /* EMIT SIGNAL */
}
}
"B overlaps the end of A"
*/
- if ((sb >= sa) && (sb <= ea)) {
+ if ((sb > sa) && (sb <= ea)) {
return OverlapEnd;
}
/*
}
};
+
Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
: SessionObject(sess, nom)
, _type(type)
/* this might not be true, but we have to act
as though it could be.
*/
+ pending_length = false;
LengthChanged (); /* EMIT SIGNAL */
+ pending_modified = false;
Modified (); /* EMIT SIGNAL */
}
}
pending_modified = true;
pending_length = true;
} else {
+ pending_length = false;
LengthChanged (); /* EMIT SIGNAL */
+ pending_modified = false;
Modified (); /* EMIT SIGNAL */
}
}
if (holding_state ()) {
pending_length = true;
} else {
+ pending_length = false;
LengthChanged(); /* EMIT SIGNAL */
+ pending_modified = false;
Modified (); /* EMIT SIGNAL */
}
}
}
pending_modified = false;
Modified (); /* EMIT SIGNAL */
+
}
for (s = dependent_checks_needed.begin(); s != dependent_checks_needed.end(); ++s) {
Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, float times)
{
RegionLock rlock (this);
-
+ delay_notifications();
times = fabs (times);
int itimes = (int) floor (times);
boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags());
add_region_internal (sub, pos);
}
+
+ release_notifications ();
}
void
void
Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, RegionList& thawlist)
{
- RegionLock rlock (this);
boost::shared_ptr<Region> region;
boost::shared_ptr<Region> current;
string new_name;
OverlapType overlap;
nframes_t pos1, pos2, pos3, pos4;
RegionList new_regions;
+ RegionList copy;
in_partition = true;
+ delay_notifications();
+
/* need to work from a copy, because otherwise the regions we add during the process
get operated on as well.
*/
-
- RegionList copy = regions;
+ {
+ RegionLock rlock (this);
+ copy = regions;
+ }
for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) {
++tmp;
current = *i;
-
+
if (current->first_frame() == start && current->last_frame() == end) {
if (cutting) {
+ RegionLock rlock (this);
remove_region_internal (current);
}
continue;
if ((overlap = current->coverage (start, end)) == OverlapNone) {
continue;
}
-
+
pos1 = current->position();
pos2 = start;
pos3 = end;
pos4 = current->last_frame();
if (overlap == OverlapInternal) {
-
+
/* split: we need 3 new regions, the front, middle and end.
cut: we need 2 regions, the front and end.
*/
/* "middle" ++++++ */
- _session.region_name (new_name, current->name(), false);
+ _session.region_name (new_name, current->name(), false); //takes the session-wide region lock
region = RegionFactory::create (current, pos2 - pos1, pos3 - pos2, new_name,
regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit));
+ RegionLock rlock (this);
add_region_internal (region, start);
new_regions.push_back (region);
}
_session.region_name (new_name, current->name(), false);
region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name,
regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
-
- add_region_internal (region, end);
- new_regions.push_back (region);
-
+ {
+ RegionLock rlock (this);
+ add_region_internal (region, end);
+ new_regions.push_back (region);
+ }
/* "front" ***** */
current->freeze ();
/* end +++++ */
_session.region_name (new_name, current->name(), false);
- region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(),
+ region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, regions.size(),
Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit));
+ RegionLock rlock (this);
add_region_internal (region, start);
new_regions.push_back (region);
}
_session.region_name (new_name, current->name(), false);
region = RegionFactory::create (current, 0, pos3 - pos1, new_name,
regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
+ RegionLock rlock (this);
add_region_internal (region, pos1);
new_regions.push_back (region);
}
*/
if (cutting) {
+ RegionLock rlock (this);
remove_region_internal (current);
}
new_regions.push_back (current);
for (RegionList::iterator i = new_regions.begin(); i != new_regions.end(); ++i) {
check_dependents (*i, false);
}
+
+ release_notifications ();
}
boost::shared_ptr<Playlist>
}
if (with_signals) {
+ pending_length = false;
LengthChanged ();
+ pending_modified = false;
Modified ();
}
/* don't send multiple Modified notifications
when multiple regions are relayered.
*/
-
+
freeze ();
/* build up a new list of regions on each layer */
copy.sort (cmp);
}
-
for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
/* find the lowest layer that this region can go on */
};
const char * const sndfile_bitdepth_formats_strings[SNDFILE_BITDEPTH_FORMATS+1] = {
- N_("16 bit"),
- N_("24 bit"),
- N_("32 bit"),
- N_("8 bit"),
- N_("float"),
+ N_("Signed 16 bit PCM"),
+ N_("Signed 24 bit PCM"),
+ N_("Signed 32 bit PCM"),
+ N_("Signed 8 bit PCM"),
+ N_("32 bit float"),
0
};